成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

八段代碼徹底掌握Promise

233jl / 2816人閱讀

摘要:異常一旦得到處理,返回的后續(xù)對(duì)象將恢復(fù)正常,并會(huì)被執(zhí)行成功的回調(diào)函數(shù)處理。另外,需要注意多級(jí)的回調(diào)函數(shù)是交替執(zhí)行的,這正是由回調(diào)的異步性決定的。

1.Promise的立即執(zhí)行性
var p = new Promise(function(resolve, reject){
  console.log("create a promise");
  resolve("success");
});

console.log("after new Promise");

p.then(function(value){
  console.log(value);
});

控制臺(tái)輸出:

"create a promise"
"after new Promise"
"success"

Promise對(duì)象表示未來某個(gè)將要發(fā)生的事件,但在創(chuàng)建(new)Promise時(shí),作為Promise參數(shù)傳入的函數(shù)是會(huì)被立即執(zhí)行的,只是其中執(zhí)行的代碼可以是異步代碼。有些同學(xué)會(huì)認(rèn)為,當(dāng)Promise對(duì)象調(diào)用then方法時(shí),Promise接收的函數(shù)才會(huì)執(zhí)行,這是錯(cuò)誤的。因此,代碼中"create a promise"先于"after new Promise"輸出。

2.Promise 三種狀態(tài)
var p1 = new Promise(function(resolve,reject){
  resolve(1);
});
var p2 = new Promise(function(resolve,reject){
  setTimeout(function(){
    resolve(2);  
  }, 500);      
});
var p3 = new Promise(function(resolve,reject){
  setTimeout(function(){
    reject(3);  
  }, 500);      
});

console.log(p1);
console.log(p2);
console.log(p3);
setTimeout(function(){
  console.log(p2);
}, 1000);
setTimeout(function(){
  console.log(p3);
}, 1000);

p1.then(function(value){
  console.log(value);
});
p2.then(function(value){
  console.log(value);
});
p3.catch(function(err){
  console.log(err);
});

控制臺(tái)輸出:

Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
1
2
3
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}

Promise的內(nèi)部實(shí)現(xiàn)是一個(gè)狀態(tài)機(jī)。Promise有三種狀態(tài):pending,resolved,rejected。當(dāng)Promise剛創(chuàng)建完成時(shí),處于pending狀態(tài);當(dāng)Promise中的函數(shù)參數(shù)執(zhí)行了resolve后,Promise由pending狀態(tài)變成resolved狀態(tài);如果在Promise的函數(shù)參數(shù)中執(zhí)行的不是resolve方法,而是reject方法,那么Promise會(huì)由pending狀態(tài)變成rejected狀態(tài)。

p2、p3剛創(chuàng)建完成時(shí),控制臺(tái)輸出的這兩臺(tái)Promise都處于pending狀態(tài),但為什么p1是resolved狀態(tài)呢? 這是因?yàn)閜1 的函數(shù)參數(shù)中執(zhí)行的是一段同步代碼,Promise剛創(chuàng)建完成,resolve方法就已經(jīng)被調(diào)用了,因而緊跟著的輸出顯示p1是resolved狀態(tài)。我們通過兩個(gè)setTimeout函數(shù),延遲1s后再次輸出p2、p3的狀態(tài),此時(shí)p2、p3已經(jīng)執(zhí)行完成,狀態(tài)分別變成resolved和rejected。

3.Promise 狀態(tài)的不可逆性
var p1 = new Promise(function(resolve, reject){
  resolve("success1");
  resolve("success2");
});

var p2 = new Promise(function(resolve, reject){
  resolve("success");
  reject("reject");
});

p1.then(function(value){
  console.log(value);
});

p2.then(function(value){
  console.log(value);
});

控制臺(tái)輸出:

"success1"
"success"

Promise狀態(tài)的一旦變成resolved或rejected時(shí),Promise的狀態(tài)和值就固定下來了,不論你后續(xù)再怎么調(diào)用resolve或reject方法,都不能改變它的狀態(tài)和值。因此,p1中resolve("success2")并不能將p1的值更改為success2,p2中reject("reject")也不能將p2的狀態(tài)由resolved改變?yōu)閞ejected.

4.鏈?zhǔn)秸{(diào)用
var p = new Promise(function(resolve, reject){
  resolve(1);
});
p.then(function(value){               //第一個(gè)then
  console.log(value);
  return value*2;
}).then(function(value){              //第二個(gè)then
  console.log(value);
}).then(function(value){              //第三個(gè)then
  console.log(value);
  return Promise.resolve("resolve"); 
}).then(function(value){              //第四個(gè)then
  console.log(value);
  return Promise.reject("reject");
}).then(function(value){              //第五個(gè)then
  console.log("resolve: "+ value);
}, function(err){
  console.log("reject: " + err);
})

控制臺(tái)輸出:

1
2
undefined
"resolve"
"reject: reject"

Promise對(duì)象的then方法返回一個(gè)新的Promise對(duì)象,因此可以通過鏈?zhǔn)秸{(diào)用then方法。then方法接收兩個(gè)函數(shù)作為參數(shù),第一個(gè)參數(shù)是Promise執(zhí)行成功時(shí)的回調(diào),第二個(gè)參數(shù)是Promise執(zhí)行失敗時(shí)的回調(diào)。兩個(gè)函數(shù)只會(huì)有一個(gè)被調(diào)用,函數(shù)的返回值將被用作創(chuàng)建then返回的Promise對(duì)象。這兩個(gè)參數(shù)的返回值可以是以下三種情況中的一種:

return 一個(gè)同步的值 ,或者 undefined(當(dāng)沒有返回一個(gè)有效值時(shí),默認(rèn)返回undefined),then方法將返回一個(gè)resolved狀態(tài)的Promise對(duì)象,Promise對(duì)象的值就是這個(gè)返回值。

return 另一個(gè) Promise,then方法將根據(jù)這個(gè)Promise的狀態(tài)和值創(chuàng)建一個(gè)新的Promise對(duì)象返回。

throw 一個(gè)同步異常,then方法將返回一個(gè)rejected狀態(tài)的Promise, 值是該異常。

根據(jù)以上分析,代碼中第一個(gè)then會(huì)返回一個(gè)值為2(1*2),狀態(tài)為resolved的Promise對(duì)象,于是第二個(gè)then輸出的值是2。第二個(gè)then中沒有返回值,因此將返回默認(rèn)的undefined,于是在第三個(gè)then中輸出undefined。第三個(gè)then和第四個(gè)then中分別返回一個(gè)狀態(tài)是resolved的Promise和一個(gè)狀態(tài)是rejected的Promise,依次由第四個(gè)then中成功的回調(diào)函數(shù)和第五個(gè)then中失敗的回調(diào)函數(shù)處理。

5.Promise then() 回調(diào)異步性
var p = new Promise(function(resolve, reject){
  resolve("success");
});

p.then(function(value){
  console.log(value);
});

console.log("which one is called first ?");

控制臺(tái)輸出:

"which one is called first ?"
"success"

Promise接收的函數(shù)參數(shù)是同步執(zhí)行的,但then方法中的回調(diào)函數(shù)執(zhí)行則是異步的,因此,"success"會(huì)在后面輸出。

6.Promise 中的異常
var p1 = new Promise( function(resolve,reject){
  foo.bar();
  resolve( 1 );      
});

p1.then(
  function(value){
    console.log("p1 then value: " + value);
  },
  function(err){
    console.log("p1 then err: " + err);
  }
).then(
  function(value){
    console.log("p1 then then value: "+value);
  },
  function(err){
    console.log("p1 then then err: " + err);
  }
);

var p2 = new Promise(function(resolve,reject){
  resolve( 2 );    
});

p2.then(
  function(value){
    console.log("p2 then value: " + value);
    foo.bar();
  }, 
  function(err){
    console.log("p2 then err: " + err);
  }
).then(
  function(value){
    console.log("p2 then then value: " + value);
  },
  function(err){
    console.log("p2 then then err: " + err);
    return 1;
  }
).then(
  function(value){
    console.log("p2 then then then value: " + value);
  },
  function(err){
    console.log("p2 then then then err: " + err);
  }
);

控制臺(tái)輸出:

p1 then err: ReferenceError: foo is not defined
p2 then value: 2
p1 then then value: undefined
p2 then then err: ReferenceError: foo is not defined
p2 then then then value: 1

Promise中的異常由then參數(shù)中第二個(gè)回調(diào)函數(shù)(Promise執(zhí)行失敗的回調(diào))處理,異常信息將作為Promise的值。異常一旦得到處理,then返回的后續(xù)Promise對(duì)象將恢復(fù)正常,并會(huì)被Promise執(zhí)行成功的回調(diào)函數(shù)處理。另外,需要注意p1、p2 多級(jí)then的回調(diào)函數(shù)是交替執(zhí)行的 ,這正是由Promise then回調(diào)的異步性決定的。

7.Promise.resolve()
var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p3 = new Promise(function(resolve, reject){
  resolve(1);
});
var p4 = new Promise(function(resolve, reject){
  resolve(p1);
});

console.log(p1 === p2); 
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

p4.then(function(value){
  console.log("p4=" + value);
});

p2.then(function(value){
  console.log("p2=" + value);
})

p1.then(function(value){
  console.log("p1=" + value);
})

控制臺(tái)輸出:

true
false
false
false
p2=1
p1=1
p4=1

Promise.resolve(...)可以接收一個(gè)值或者是一個(gè)Promise對(duì)象作為參數(shù)。當(dāng)參數(shù)是普通值時(shí),它返回一個(gè)resolved狀態(tài)的Promise對(duì)象,對(duì)象的值就是這個(gè)參數(shù);當(dāng)參數(shù)是一個(gè)Promise對(duì)象時(shí),它直接返回這個(gè)Promise參數(shù)。因此,p1 === p2。但通過new的方式創(chuàng)建的Promise對(duì)象都是一個(gè)新的對(duì)象,因此后面的三個(gè)比較結(jié)果都是false。另外,為什么p4的then最先調(diào)用,但在控制臺(tái)上是最后輸出結(jié)果的呢?因?yàn)閜4的resolve中接收的參數(shù)是一個(gè)Promise對(duì)象p1,resolve會(huì)對(duì)p1”拆箱“,獲取p1的狀態(tài)和值,但這個(gè)過程是異步的,可參考下一節(jié)。

8.resolve vs reject
var p1 = new Promise(function(resolve, reject){
  resolve(Promise.resolve("resolve"));
});

var p2 = new Promise(function(resolve, reject){
  resolve(Promise.reject("reject"));
});

var p3 = new Promise(function(resolve, reject){
  reject(Promise.resolve("resolve"));
});

p1.then(
  function fulfilled(value){
    console.log("fulfilled: " + value);
  }, 
  function rejected(err){
    console.log("rejected: " + err);
  }
);

p2.then(
  function fulfilled(value){
    console.log("fulfilled: " + value);
  }, 
  function rejected(err){
    console.log("rejected: " + err);
  }
);

p3.then(
  function fulfilled(value){
    console.log("fulfilled: " + value);
  }, 
  function rejected(err){
    console.log("rejected: " + err);
  }
);

控制臺(tái)輸出:

p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject

Promise回調(diào)函數(shù)中的第一個(gè)參數(shù)resolve,會(huì)對(duì)Promise執(zhí)行"拆箱"動(dòng)作。即當(dāng)resolve的參數(shù)是一個(gè)Promise對(duì)象時(shí),resolve會(huì)"拆箱"獲取這個(gè)Promise對(duì)象的狀態(tài)和值,但這個(gè)過程是異步的。p1"拆箱"后,獲取到Promise對(duì)象的狀態(tài)是resolved,因此fulfilled回調(diào)被執(zhí)行;p2"拆箱"后,獲取到Promise對(duì)象的狀態(tài)是rejected,因此rejected回調(diào)被執(zhí)行。但Promise回調(diào)函數(shù)中的第二個(gè)參數(shù)reject不具備”拆箱“的能力,reject的參數(shù)會(huì)直接傳遞給then方法中的rejected回調(diào)。因此,即使p3 reject接收了一個(gè)resolved狀態(tài)的Promise,then方法中被調(diào)用的依然是rejected,并且參數(shù)就是reject接收到的Promise對(duì)象。

歡迎關(guān)注我的公眾號(hào):老干部的大前端,領(lǐng)取21本大前端精選書籍!

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/84308.html

相關(guān)文章

  • 關(guān)于Promise

    摘要:反之,操作失敗,對(duì)象由狀態(tài)轉(zhuǎn)換為狀態(tài),此時(shí)回調(diào)函數(shù)會(huì)執(zhí)行方法。這里需要注意的是,雖然在之后便執(zhí)行了方法,但是并不是意味著往后的對(duì)象不執(zhí)行了,其他的還是對(duì)象還是要執(zhí)行的,只是不會(huì)再調(diào)用函數(shù)。 在 掘金上看見一篇寫promise的文章,感覺作者寫的很棒,文章鏈接在這:八段代碼徹底掌握 Promise 。看完之后感覺學(xué)到了很多,所以又重新把JavaScript Promise迷你書(中文版)...

    546669204 評(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
  • ES6-7

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

    mudiyouyou 評(píng)論0 收藏0
  • JavasScript重難點(diǎn)知識(shí)

    摘要:忍者級(jí)別的函數(shù)操作對(duì)于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對(duì)于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...

    forsigner 評(píng)論0 收藏0
  • 2017-07-26 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選庖丁解牛二深入解析模板字符串八段代碼徹底掌握高效壓縮文件束的體積譯才不是什么黑魔法呢發(fā)布中文譯數(shù)據(jù)結(jié)構(gòu)棧與隊(duì)列瘋狂的技術(shù)宅中自定義指令修仙之路更好的異步解決方案發(fā)布同步代碼書寫異步情懷有贊前端團(tuán)隊(duì)位運(yùn)算,也許 2017-07-26 前端日?qǐng)?bào) 精選 庖丁解牛React-Redux(二): connect深入解析 ES6:模板字符串_ES6八段代碼徹底掌握Promise高效壓縮...

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

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

0條評(píng)論

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