摘要:初識對象是一個構造函數(shù),其接受一個函數(shù)作為參數(shù),為這個函數(shù)的參數(shù),函數(shù)內(nèi)部一般為異步執(zhí)行的代碼,作為異步執(zhí)行完成之后成功的回調(diào),作為異步執(zhí)行拋錯的回調(diào)。構造函數(shù)可以理解為執(zhí)行異步的過程,其和為執(zhí)行異步調(diào)用結果的回調(diào)函數(shù)。
初識Promise
Promise對象是一個構造函數(shù),其接受一個函數(shù)作為參數(shù),resolve、reject為這個函數(shù)的參數(shù),函數(shù)內(nèi)部一般為異步執(zhí)行的代碼,resolve作為異步執(zhí)行完成之后成功的回調(diào),reject作為異步執(zhí)行拋錯的回調(diào)。Promise構造函數(shù)可以理解為執(zhí)行異步的過程,其resolve和reject為執(zhí)行異步調(diào)用結果的回調(diào)函數(shù)。
// 代碼1 var p = new Promise((resolve, reject) => { // 執(zhí)行一系列的異步執(zhí)行 // some codes... if (true) { resolve("異步執(zhí)行成功"); } else { reject("異步執(zhí)行拋錯"); } }); // fulfilled: 異步執(zhí)行成功 ; 非fulfilled: 異步執(zhí)行拋錯Promise的異步處理 then和catch的使用
Promise構造函數(shù)返回一個異步執(zhí)行之后的promise對象,該對象對異步的結果進一步處理。
// 代碼2 p .then((res) => { // try catch 手動拋錯 try { // console.log("異步返回成功狀態(tài)"); throw Error("錯誤代碼"); } catch(e) { console.log("執(zhí)行catch"); return Promise.reject(e); } }) .catch((res) => { console.log(res); // 輸出上一個 then 中 catch 的 e return "這里由錯誤信息過去的數(shù)據(jù)"; }) .then((res) => { console.log(res); // 若上一個catch執(zhí)行,輸出:這里由錯誤信息過去的數(shù)據(jù) })
以上代碼執(zhí)行結果:
# 結果1 執(zhí)行catch Error: 錯誤代碼 at p.then (**/promise.js:77:10) at process._tickCallback (internal/process/next_tick.js:109:7) at Module.runMain (module.js:607:11) at run (bootstrap_node.js:423:7) at startup (bootstrap_node.js:147:9) at bootstrap_node.js:538:3 這里由錯誤信息過去的數(shù)據(jù)promise對象的鏈式調(diào)用
由代碼2可以看出,promise對象狀態(tài)為resolve的時候,執(zhí)行then方法,而且在不拋錯情況下會持續(xù)執(zhí)行鏈式調(diào)用的then方法,若then方法拋出異?;蛘邟伋龇祷?b>Promise.reject()方法,會轉到執(zhí)行catch方法,若catch方法返回的不是Promise.reject()方法或者不拋出異常,則所有使用return返回的數(shù)據(jù)都會作為參數(shù)傳給下一個then函數(shù)參數(shù)的參數(shù),即代碼2中的最后一個then方法指定函數(shù)參數(shù)的res是上一個catch所return的數(shù)據(jù)。
var p = new Promise((resolve, reject) => { resolve("ok"); }); p.then((msg) => { console.log(msg); return Promise.reject("then01拋錯"); }).catch((errMsg) => { console.warn(errMsg); }).then(() => { console.log("then02再執(zhí)行"); }).then(() => { console.log("then03再執(zhí)行"); return Promise.reject("then03拋錯"); }).catch((errMsg) => { console.warn(errMsg); return "catch02 return 給下一個then指定方法的值"; }).then((msg) => { console.log(msg); });
運行結果如下:
這是因為then方法和catch方法返回的都是一個promise對象。then方法指定的回調(diào)函數(shù)拋出錯誤會被下一個catch方法捕獲,多個then方法執(zhí)行也是如此。catch方法會捕獲上一個catch方法(如果有的話)之后拋錯的錯誤。
Promise狀態(tài)換言之,無論是then方法還是catch方法,返回的都是一個promise對象,其狀態(tài)取決于上一個方法指定的函數(shù)是否順利執(zhí)行或者沒有返回Promise.reject()。
一旦Promise的狀態(tài)變?yōu)閞esolved或者rejected,就會永久保持該狀態(tài),不會再變。
var p = new Promise((resolve, reject) => { resolve("ok"); throw new Error("wrong"); }); p.then((msg) => { console.log(msg); }).catch((errMsg) => { console.warn(errMsg); }); // ok
在Promise的參數(shù)函數(shù)中,由于先斷定了resolved狀態(tài),所以在之后只會執(zhí)行then函數(shù),后面拋出的錯誤會等于沒拋出來。
另外,“事件循環(huán)”會對拋出的結果有影響。
var p = new Promise((resolve, reject) => { resolve("ok"); setTimeout(() => { throw new Error("wrong"); }, 0); }); p.then((msg) => { console.log(msg); }).catch((errMsg) => { console.warn(errMsg); }); // ok // 瀏覽器拋出的錯誤 // index.js:4 Uncaught Error: wrong // at setTimeout (index.js:4) // setTimeout @ index.js:4
在本輪“事件循環(huán)”中,promise對象p先執(zhí)行,所以構造函數(shù)Promise的指定函數(shù)先輸出‘ok’;在進入到下一次的“事件循環(huán)”的時候,由于Promise函數(shù)體已經(jīng)執(zhí)行完畢,故后面拋出的錯誤是在Promise函數(shù)體外拋出的,Promise函數(shù)體無法捕獲到這個錯誤。
Promise.resolve()Promise.resolve()接受一個參數(shù),其返回一個promise對象的狀態(tài)會因為傳入的參數(shù)的不同而不同。
參數(shù)分別以下幾種情況:空
返回一個狀態(tài)為resolved的promise對象,也就是下一步會執(zhí)行then方法。
var p = Promise.resolve(); p.then((res) => { console.log("then"); }).catch((res) => { console.log("catch"); }); // then
thenable對象
var thenable = { then: function (resolve, reject) { console.log("立即執(zhí)行thenable的then的方法" + Date.now()); resolve("斷定之后的信息"); } } var p = Promise.resolve(thenable); p.then((res) => { console.log(res); }); // 立即執(zhí)行thenable的then的方法1494485393447 // 斷定之后的信息 // 相當于 var p = new Promise(function (resolve, reject) { console.log("立即執(zhí)行thenable的then的方法" + Date.now()); resolve("斷定之后的信息"); }); p.then((res) => { console.log(res); }); // 立即執(zhí)行thenable的then的方法1494485454503 // 斷定之后的信息
thenable對象作為參數(shù),在執(zhí)行Promise.resolve(thenable)方法的時候,會立即執(zhí)行thenable對象中的then方法,并且其返回的Promise對象的狀態(tài)取決于thenable對象的then方法執(zhí)行的是resolve()還是reject()。這種情況下,就相當于Promise構造函數(shù)以thenable對象的then方法作為參數(shù),實例化一個Promise實例。
一個非Promise對象,且不含有then方法的對象------非thenable對象
var p = Promise.resolve({ a: 1 }); p.then((res) => { console.log(res); }); // { a: 1 } var p01 = Promise.resolve("Hello Promise!"); p01.then((res) => { console.log(res); }); // Hello Promise!
這種情況下,Promise.resolve()的狀態(tài)為resolved,其接收的參數(shù)會作為then方法指定函數(shù)的參數(shù)。
Promise對象
var p01 = new Promise((resolve, reject) => { reject("Throw some error! Come on! You bite me."); }); var p = Promise.resolve(p01); p.then((res) => { console.log("這是then方法"); }).catch((errMsg) => { console.log(errMsg); }); // Throw some error! Come on! You bite me.
傳入的是一個Promise對象,Promise.resolve()返回的對象的狀態(tài)就是傳入的Promise對象的狀態(tài)。
Promise.reject()Promise.reject(reason)方法同樣返回一個狀態(tài)為rejected的Promise對象實例。值得注意的是,參數(shù)reason(Promise狀態(tài)rejected的原因)不論是什么值,都會傳給返回的Promise對象的catch方法指定的函數(shù)作為參數(shù)。
var p = Promise.reject("Throw some error! Come on! You bite me."); p.then((res) => { console.log("這是then方法"); }).catch((errMsg) => { console.log(errMsg); }); // Throw some error! Come on! You bite me.promise對象的使用場景——圖片加載
var imgPromise = function (url) { return new Promise((resolve, reject) => { var img = new Image(); img.src = url; img.onload = resolve; img.onerror = reject; }); } imgPromise("http://imgurl") .then((res) => { console.log("圖片加載完成"); }) .catch((res) => { console.log("圖片加載失敗"); }):
參考文章
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/82808.html
摘要:上代碼異步執(zhí)行成功的構造函數(shù)接收一個函數(shù)參數(shù),并傳入兩個參數(shù),分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù)。第一個回調(diào)函數(shù)是對象的狀態(tài)變?yōu)闀r調(diào)用,第二個回調(diào)函數(shù)是對象的狀態(tài)變?yōu)闀r調(diào)用。 這篇文章只解決三個問題。什么是promise? promise有什么用?promise怎么用? 1.什么是promise? 對于ES6來說,就是一個構造函數(shù),可以用new Prom...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網(wǎng)絡基礎知識之 HTTP 協(xié)議 詳細介紹 HTT...
摘要:的翻譯文檔由的維護很多人說,阮老師已經(jīng)有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:今天對于處理異步調(diào)用已經(jīng)有了很多成熟的方案,在我看來這些方案都無外乎在解決一個問題如何能看似順序地傳遞異步調(diào)用的結果,本文要說的就是原生提供的一個解決方案。在對進行敘述之前,依舊引用阮大的入門一書中的章節(jié)便于大家更嚴謹和全面的學習和參考。 異步回調(diào)的泥潭 異步回調(diào)是最直接的異步結果處理模式,將一個回調(diào)函數(shù)callback扔進異步處理函數(shù)中,當異步處理獲得結果之后再調(diào)用這個回調(diào)函數(shù)就可以...
摘要:源碼學習本篇為上一篇源碼學習的補充,主要是來介紹和方法。那個率先改變的實例的返回值,就傳遞給的回調(diào)函數(shù)。基本介紹可見阮一峰老師的書籍。的狀態(tài)由決定,分成兩種情況。只有的狀態(tài)都變成,的狀態(tài)才會變成,此時的返回值組成一個數(shù)組,傳遞給的回調(diào)函數(shù)。 Promise源碼學習(2) 本篇為上一篇源碼學習(1)的補充,主要是來介紹Promise.all()和Promise.race()方法。閑話少敘...
閱讀 1621·2023-04-26 02:43
閱讀 3040·2021-11-11 16:54
閱讀 1362·2021-09-23 11:54
閱讀 1181·2021-09-23 11:22
閱讀 2372·2021-08-23 09:45
閱讀 855·2019-08-30 15:54
閱讀 3107·2019-08-30 15:53
閱讀 3197·2019-08-30 15:53