国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深度理解Promise--Promise的特點(diǎn)和方法詳解

wqj97 / 1398人閱讀

摘要:實(shí)例生成以后,用方法分別指定狀態(tài)和狀態(tài)的回調(diào)函數(shù)。則是或的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。上述代碼也可以理解成這樣處理和前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤發(fā)生錯(cuò)誤方法用于指定不管對(duì)象最后狀態(tài)如何,都會(huì)執(zhí)行的回調(diào)函數(shù)。

什么是promise?

Promise(承諾),在程序中的意思就是承諾我過一段時(shí)間(通常是一個(gè)異步操作)后會(huì)給你一個(gè)結(jié)果,是異步編程的一種解決方案。從語法上說,原生Promise 是一個(gè)對(duì)象,從它可以獲取異步操作的消息。

promise的特點(diǎn)

對(duì)象的狀態(tài)不受外界影響。

promise有三種狀態(tài) pending(進(jìn)行中) fulfilled(已成功) rejected(已失敗),只有異步操作的結(jié)果,才可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個(gè)狀態(tài)。

一旦從等待狀態(tài)變成為其他狀態(tài)就永遠(yuǎn)不能更改狀態(tài)了。

promise只有兩種狀態(tài)改變:
pending(進(jìn)行中)--> fulfilled(已成功) ;
pending(進(jìn)行中)--> rejected(已失敗)。
當(dāng)狀態(tài)改變結(jié)束時(shí)稱為resolve(已固定),一旦狀態(tài)變?yōu)?resolved 后,就不能再次改變?yōu)?b>Fulfilled。

一旦新建Promise就會(huì)立即執(zhí)行,無法中途取消。

如果不設(shè)置回調(diào)函數(shù)callback,Promise內(nèi)部拋出的錯(cuò)誤,就不會(huì)反應(yīng)到外部。

當(dāng)處于pending狀態(tài)時(shí),無法得知目前進(jìn)展到哪一個(gè)階段(剛剛開始還是即將完成)。

promise實(shí)例操作

首先創(chuàng)造了一個(gè)Promise實(shí)例

let promise=new Promsie(function(resolve,rejec){
    if(/*異步執(zhí)行成功*/){
        resolve(value);
    }else{
        reject(error);
    }
})
promise.then(function(){
    //回調(diào)執(zhí)行成功之后的操作
},function(){
    //回調(diào)執(zhí)行失敗之后的操作,可選
});

Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolve和reject。它們是兩個(gè)函數(shù),由 JavaScript 引擎提供。當(dāng)異步操作成功時(shí)(pending--fulfilled),調(diào)用resolve(value)函數(shù)把操作結(jié)果當(dāng)成參數(shù)傳出,當(dāng)異步操作成功時(shí)(pending--rejected)調(diào)用 reject(error)函數(shù)把錯(cuò)誤返回。Promise實(shí)例生成以后,用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)。

下面看一下構(gòu)造函數(shù)原型的方法

Promise.prototype.then()

Promise.prototype.then()作用是為 Promise 實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)。接受兩個(gè)回調(diào)函數(shù)作為參數(shù)。第一個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞esolved時(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞ejected時(shí)調(diào)用。其中,第二個(gè)函數(shù)是可選的,不一定要提供。

Promise.prototype.then()返回的是另一個(gè)Promise對(duì)象,后面還可以接著調(diào)用then方法。

Promise.prototype.catch()

Promise.prototype.catch()則是.then(null, rejection).then(undefined, rejection)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。 Promise 對(duì)象的錯(cuò)誤具有“冒泡”性質(zhì),會(huì)一直向后傳遞,直到被捕獲為止。也就是說,錯(cuò)誤總是會(huì)被下一個(gè)catch語句捕獲

Promise.catch()方法返回的也是一個(gè) Promise 對(duì)象,因此后面還可以接著調(diào)用then方法。

上述代碼也可以理解成這樣:

getJSON("/posts.json").then(function(posts) {
      // ...
}).catch(function(error) {
  // 處理 getJSON 和 前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤
  console.log("發(fā)生錯(cuò)誤!", error);
});

Promise.prototype.finally()

finally方法用于指定不管 Promise 對(duì)象最后狀態(tài)如何,都會(huì)執(zhí)行的回調(diào)函數(shù)。該方法是 ES2018 引入標(biāo)準(zhǔn)的。

finally方法的回調(diào)函數(shù)不接受任何參數(shù),這意味著沒有辦法知道,前面的 Promise 狀態(tài)到底是fulfilled還是rejected。這表明,finally方法里面的操作,應(yīng)該是與狀態(tài)無關(guān)的,不依賴于 Promise 的執(zhí)行結(jié)果。

finally本質(zhì)上是then方法的特例。

promise.then(()=>{}).catch(()=>{}).finally(() => {
      // 操作
});
// 等同于
promise.then(result => {
        // 操作
    return result;
}).catch( error => {
        // 操作
    throw error;
});

promise的鏈?zhǔn)秸{(diào)用

由于 .then每次調(diào)用返回的都是一個(gè)新的Promise實(shí)例,如果then中返回的是一個(gè)結(jié)果的話會(huì)把這個(gè)結(jié)果傳遞下一次then中的成功回調(diào),所以可以鏈?zhǔn)秸{(diào)用該實(shí)例。

如果then中出現(xiàn)異常,會(huì)走下一個(gè)then的失敗回調(diào),catch 會(huì)捕獲到?jīng)]有捕獲的異常。

在 then中使用了return,那么 return 的值會(huì)被Promise.resolve() 包裝,then中也可以不傳遞參數(shù),如果不傳遞會(huì)透到下一個(gè)then中。

Promise.resolve(1).then(res => {
        console.log(res)
        return 2 //包裝成 Promise.resolve(2)
}).catch(err => 3).then().then(res => console.log(res))

promise自身API

Promise.resolve()

將現(xiàn)有的對(duì)象轉(zhuǎn)換(包裝)成 promise對(duì)象。
四種參數(shù)類型:

不帶參數(shù)傳遞 --- 返回一個(gè)新的狀態(tài)為resolve的promise對(duì)象。

let p = Priomse.resolve()   // p就是promise

參數(shù)是一個(gè) Promise 實(shí)例--- 返回 當(dāng)前的promise實(shí)例

參數(shù)是帶then方法的對(duì)象

let data = {
    then:function(resolve,reject){
        resovle("帶then方法的對(duì)象")
    }
}
Promise.resolve(data).thne((res)=> console.log(res)) // "帶then方法的對(duì)象"

返回一個(gè)新的promise,并直接執(zhí)行then的方法,promise對(duì)象的狀態(tài)就變?yōu)?b>resolved,從而立即執(zhí)行最后那個(gè)then方法指定的回調(diào)函數(shù),輸出 "帶then方法的對(duì)象"

參數(shù)是非空,非then方法的對(duì)象,非proimse的

let p = Promise.resolve("foo")
// 等價(jià)于
let p = new Promise(resolve => resolve("foo"))
p.then(res=>console.log(res)) //"foo"

返回一個(gè)新的狀態(tài)為resolve的promise對(duì)象,所以then回調(diào)函數(shù)會(huì)立即執(zhí)行。Promise.resolve方法的參數(shù),會(huì)同時(shí)傳給回調(diào)函數(shù)。

Promise.reject()

參數(shù)為非then對(duì)象時(shí)-----Promise.reject(reason)方法也會(huì)返回一個(gè)新的 Promise 實(shí)例,該實(shí)例的狀態(tài)為rejected

let p  =  Promise.reject("error")
// 等價(jià)于
let p = new Primose((resolve,reject)=>reject("出錯(cuò)了")})
//處理錯(cuò)誤的回調(diào)
p.then((null,res)=>console.log(res)) //"出錯(cuò)了"

參數(shù)是帶then方法的對(duì)象 ---返回的并不是then方法的回調(diào)函數(shù),而是data對(duì)象本身

let data = {
    then:function(resolve,reject){
        reject("帶then方法的對(duì)象出錯(cuò)了")
    }
}
Promise.resolve(data).thne((null,res)=> console.log(res)) // data 
//等同于
Promise.resolve(data).catch(res=> console.log(res)) // data 

Promise.all()
該方法將多個(gè)promise實(shí)例,包裝成一個(gè)新的promise實(shí)例。

    let p = Promise.all([p1,p2,p3])

參數(shù)不一定為數(shù)組,但必須為一個(gè)可迭代Iterator ,且返回的每個(gè)成員(p1,p2,p3)都是 Promise 實(shí)例,如果不是,就會(huì)先調(diào)用的Promise.resolve方法,將參數(shù)轉(zhuǎn)為 Promise 實(shí)例,再進(jìn)一步處理。

var p = Promise.all([1,2,3]);
var p2 = Promise.all([1,2,3, Promise.resolve(444)]);
var p3 = Promise.all([1,2,3, Promise.reject(555)]);
setTimeout(function() {
    console.log(p);// Promise { : "fulfilled", : Array[3] }
       console.log(p2); // Promise { : "fulfilled", : Array[4] }
    console.log(p3); // Promise { : "rejected", : 555 }
});
p.then(function (posts) {
  // ..當(dāng)有返回值的時(shí)候才會(huì)回調(diào)
}).catch(function(reason){
  // ...
});

當(dāng)p1,p2,p3中得實(shí)例都改變成 fulfilled(已成功)時(shí),此時(shí)p1、p2、p3的返回值組成一個(gè)數(shù)組,傳遞給p的回調(diào)函數(shù)。

當(dāng)p1,p2,p3中得實(shí)例其中一項(xiàng)的改變成 rejected(已失敗)時(shí),p的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的返回值,會(huì)傳遞給p的回調(diào)函數(shù)。

Promise.all()是異步解析,只有這當(dāng)所有實(shí)例的狀態(tài)都變成fulfilled,或者其中有一個(gè)變?yōu)?b>rejected,才會(huì)調(diào)用Promise.all方法后面的回調(diào)函數(shù)then,catch方法。但是當(dāng)且僅當(dāng)傳遞的iterable為空時(shí),Promise.all才會(huì)同步解析

var p = Promise.all([]); 
console.log(p);//Promise { : "fulfilled", : Array[0] }

處理錯(cuò)誤,常規(guī)情況下,當(dāng)其中一個(gè)實(shí)例返回rejected,就會(huì)調(diào)用Promise.allcatch方法,返回第一個(gè)錯(cuò)誤。但實(shí)際應(yīng)用時(shí),我們想讓所有的實(shí)例不論成功或失敗就可以返回參數(shù)組成數(shù)組,這時(shí)就可以調(diào)用實(shí)例自身的catch方法來規(guī)避這種情況。

const p1 = new Promise((resolve, reject) => {
  resolve("hello"); //resolved
}).then(result => result).catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error("報(bào)錯(cuò)了");//rejected
}).then(result => result).catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result))// ["hello", Error: 報(bào)錯(cuò)了]
.catch(e => console.log(e));

p1會(huì)resolved,p2首先會(huì)rejected,但是p2有自己的catch方法,該方法返回的是一個(gè)新的 Promise 實(shí)例,p2指向的實(shí)際上是這個(gè)實(shí)例。該實(shí)例執(zhí)行完catch方法后,也會(huì)變成resolved,導(dǎo)致Promise.all()方法參數(shù)里面的兩個(gè)實(shí)例都會(huì)resolved,因此會(huì)調(diào)用then方法指定的回調(diào)函數(shù),而不會(huì)調(diào)用catch方法指定的回調(diào)函數(shù)。

js原生實(shí)現(xiàn)Promise.all的原理

//在Promise類上添加一個(gè)all方法,接受一個(gè)傳進(jìn)來的promise數(shù)組
Promise.all = function (promiseArrs) { 
   return new Promise((resolve, reject) => { //返回一個(gè)新的Promise
    let arr = []; //定義一個(gè)空數(shù)組存放結(jié)果
    let i = 0;
    function handleData(index, data) { //處理數(shù)據(jù)函數(shù)
        arr[index] = data;
        i++;
        if (i === promiseArrs.length) { //當(dāng)i等于傳遞的數(shù)組的長度時(shí) 
            resolve(arr); //執(zhí)行resolve,并將結(jié)果放入
        }
    }
    for (let i = 0; i < promiseArrs.length; i++) { //循環(huán)遍歷數(shù)組
        promiseArrs[i].then((data) => {
            handleData(i, data); //將結(jié)果和索引傳入handleData函數(shù)
        }, reject)
    }
    })
}

如果說all體驗(yàn)不好,那我們也可以自己做一個(gè)some方法,表示全部失敗才算失敗

Promise.some = function (promiseArrs) {
  return new Promise((resolve, reject) => {
  let arr = []; //定義一個(gè)空數(shù)組存放結(jié)果
  let i = 0;
  function handleErr(index, err) { //處理錯(cuò)誤函數(shù)
      arr[index] = err;
      i++;
      if (i === promiseArrs.length) { //當(dāng)i等于傳遞的數(shù)組的長度時(shí) 
        reject(err); //執(zhí)行reject,并將結(jié)果放入
      }
  }
  for (let i = 0; i < promiseArrs.length; i++) { //循環(huán)遍歷數(shù)組
      promiseArrs[i].then(resolve, (e) => handleErr(i, e))
  }
  })
}

Promise.allSettled -- 兼容性不友好
該方法和promise.all類似,就是解決all方法在處理錯(cuò)誤時(shí)的不合理而出現(xiàn)的。其參數(shù)接受一個(gè)Promise的數(shù)組, 返回一個(gè)新的Promise, 唯一與all的不同在于, 其不會(huì)進(jìn)行短路, 也就是說當(dāng)Promise全部處理完成后我們可以拿到每個(gè)Promise的狀態(tài), 而不管其是否處理成功。

和all類似,當(dāng)自身實(shí)例有catch回調(diào)時(shí),每個(gè)實(shí)例狀態(tài)變?yōu)?b>fulfilled

const p3 = new Promise((resolve, reject) => {
  resolve("hello"); //resolved
}).then(result => result).catch(e => e);

const p4 = new Promise((resolve, reject) => {
  throw new Error("報(bào)錯(cuò)了");//rejected
}).then(result => result).catch(e => e);

Promise.allSettled([p3, p4])
.then(result => console.log(result))
.catch(e => console.log(e));
//.then的log
//[{status: "fulfilled", value: "hello"},{status: "fulfilled", reason: Error: 報(bào)錯(cuò)了 at :6:10 at     new Promise () at :5:13}]

沒有catch接收錯(cuò)誤,返回自身的狀態(tài)和回調(diào)參數(shù)

const p5 = new Promise((resolve, reject) => {
  resolve("hello"); //resolved
}).then(result => result)

const p6 = new Promise((resolve, reject) => {
  throw new Error("報(bào)錯(cuò)了");//rejected
}).then(result => result)

Promise.allSettled([p5, p6])
.then(result => console.log(result))
.catch(e => console.log(e));
//.then的log
//[{status: "fulfilled", value: "hello"},{status: "rejected", reason: Error: 報(bào)錯(cuò)了 at :6:10 at     new Promise () at :5:13}]

Promise.race()

該方法同樣是將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例,其他特點(diǎn)和all很像,和all的區(qū)別在于:race方法好比是賽跑,幾個(gè)實(shí)例一起跑,誰先到就成功了,就resolve誰,或者誰跑到中途摔了出現(xiàn)異常狀況失敗了,就reject誰,不論成功還是失敗,就先捕獲第一個(gè)完成的。

捕獲第一個(gè)成功的實(shí)例回調(diào)函數(shù)

let p1 = Promise.resolve("1")
let p2 = Promise.resolve("2")
Promise.race([p1,p2]).then(res=>conseloe.log(res))// "1"

捕獲第一個(gè)結(jié)果

let p1 = Promise.resolve("1");
  let p2 = Promise.reject("ERR2");
 Promise.race([p1,p2]).then(res=>conseloe.log(res)) //Promise {: "1"}

捕獲第一個(gè)錯(cuò)誤

let p1 = Promise.reject("ERR1");
  let p2 = Promise.reject("ERR2");
 Promise.race([p1,p2]).catch(console.log) //Promise {: "ERR1"}

原生實(shí)現(xiàn)Promise.race()的設(shè)計(jì)原理

Promise._race = iterator  =>{
    return new Promise((resolve,reject)=>{
        iterator.forEach(item=>{
            Promise.resolve(item).then(resolve).catch(reject)
        })
    })
}

Promise.try-- 提案

在實(shí)際開發(fā)使用promise時(shí),希望經(jīng)過promise包裝后的函數(shù)內(nèi)部代碼讓同步函數(shù)同步執(zhí)行,異步函數(shù)異步執(zhí)行,并且讓它們具有統(tǒng)一的 API
例:當(dāng)同步函數(shù)被promise包裝后的執(zhí)行順序改變。

let fn = () =>console.log("同步1");
Promise.resolve().then(fn)
console.log("同步2")
//log后
//"同步2"
//"同步1"

解決讓同步函數(shù)同步執(zhí)行,異步函數(shù)異步執(zhí)行現(xiàn)階段方法

方法一:使用async匿名函數(shù),會(huì)立即執(zhí)行里面的async函數(shù),因此如果f是同步的,就會(huì)得到同步的結(jié)果;如果f是異步的,就可以用then指定下一步,如果想捕獲錯(cuò)誤,使用catch方法。

 let fn = () =>console.log("同步1");
 (async ()=>fn())()
 .then(resolve)
 .catch(err=>console.log(err))
 console.log("同步2")
 //log后
 //"同步1"
//"同步2"

方法二:使用promise立即執(zhí)行的匿名函數(shù)

 let fn = () =>console.log("同步1");
(
    () => new Promise(
       resolve => resolve(fn())
 ))()
console.log("同步2")
//log后
//"同步1"
   //"同步2"

Promise.try的應(yīng)用
該方法是用來模擬try的代碼塊的,就像promise.catch模擬的是catch代碼塊。

理解 try catch finally

 try catch是JavaScript的異常處理機(jī)制,把可能出錯(cuò)的代碼放在try語句塊中,如果出錯(cuò)了,就會(huì)被catch捕獲來處理異常。如果不catch 一旦出錯(cuò)就會(huì)造成程序崩潰。finally:無論結(jié)果如何,允許在 try 和 catch 之后執(zhí)行代碼。
try {
        // 供測試的代碼塊
}
 catch(err) {
         //處理錯(cuò)誤的代碼塊
} 
finally {
         //無論 try / catch 結(jié)果如何都執(zhí)行的代碼塊
}

應(yīng)用

let fn = () => console.log("同步1");
  Promise.try(fn);
  console.log("同步2");
  //"同步1"
  //"同步2"

over~有問題留言
拓展:

什么是Iterator ?

異步編程是什么? 異步編程都有哪些解決方案?

如何使用promise實(shí)現(xiàn)ajax,封裝axios?

如何使用純原生js實(shí)現(xiàn)promise?

借鑒:
https://blog.csdn.net/sjw1039...
http://es6.ruanyifeng.com/#do...
https://developer.mozilla.org...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106813.html

相關(guān)文章

  • ES6-7

    摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評(píng)論0 收藏0
  • JavaScript 異步

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個(gè)符合規(guī)范并可配合使用的寫一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過...

    tuniutech 評(píng)論0 收藏0
  • 前端基礎(chǔ)進(jìn)階(十二):深入核心,詳解事件循環(huán)機(jī)制

    摘要:前端基礎(chǔ)進(jìn)階正是圍繞這條線索慢慢展開,而事件循環(huán)機(jī)制,則是這條線索的最關(guān)鍵的知識(shí)點(diǎn)。特別是中正式加入了對(duì)象之后,對(duì)于新標(biāo)準(zhǔn)中事件循環(huán)機(jī)制的理解就變得更加重要。之后全局上下文進(jìn)入函數(shù)調(diào)用棧。 showImg(https://segmentfault.com/img/remote/1460000008811705); JavaScript的學(xué)習(xí)零散而龐雜,因此很多時(shí)候我們學(xué)到了一些東西,但...

    whjin 評(píng)論0 收藏0
  • 淺談不同環(huán)境下JavaScript執(zhí)行機(jī)制 + 示例詳解

    摘要:如果沒有其他異步任務(wù)要處理比如到期的定時(shí)器,會(huì)一直停留在這個(gè)階段,等待請求返回結(jié)果。執(zhí)行的執(zhí)行事件關(guān)閉請求的,例如事件循環(huán)的每一次循環(huán)都需要依次經(jīng)過上述的階段。因此,才會(huì)早于執(zhí)行。 showImg(https://segmentfault.com/img/bVbnY76); 概念 同步任務(wù)(Synchronous) 在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù) ...

    wanghui 評(píng)論0 收藏0
  • Javascript異步編程:Callback、Promise、Generator

    摘要:異步過程控制了解異步的意義之后,我們來對(duì)比目前主流幾種異步過程控制方法,探討一下異步編程的最佳實(shí)踐。結(jié)語希望本文對(duì)大家有點(diǎn)幫助,能更深刻的理解異步編程,能寫出更優(yōu)雅更高效的代碼。 同步和異步(Synchronous and Asynchronous) 了解javascript的同學(xué)想必對(duì)同步和異步的概念應(yīng)該都很熟悉了,如果還有不熟悉的同學(xué),我這里舉個(gè)形象的例子,比如我們早上起床后要干三...

    dadong 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<