摘要:回調(diào)函數(shù)是的一大特色官方的基本都是以會(huì)回調(diào)方式傳遞函數(shù)返回值。針對(duì)這種普遍問(wèn)題,應(yīng)勢(shì)而生基本用法創(chuàng)建做一些異步操作的事情,然后一切正常的構(gòu)造器接受一個(gè)函數(shù)作為參數(shù),它會(huì)傳遞給這個(gè)回調(diào)函數(shù)兩個(gè)變量和。
Promise 是什么?
Promise 對(duì)象用來(lái)進(jìn)行延遲(deferred) 和 異步(asynchronous) 計(jì)算。
一個(gè) Promise 處于以下三種狀態(tài)之一:
pending: 初始狀態(tài), 非 fulfilled 或 rejected.
fulfilled: 成功的操作.
rejected: 失敗的操作.
Promise 接口表示為一個(gè)值的代理,這個(gè)值在promise創(chuàng)建時(shí)未必已知. 它允許你將 handlers 與一個(gè)異步 action 最終的成功或失敗狀態(tài)關(guān)聯(lián)起來(lái). 這使得異步方法可以像同步方法那樣返回值: 異步方法返回一個(gè)在未來(lái)某個(gè)時(shí)刻擁有一個(gè)值的 promise 來(lái)替代最終返回值.
pending狀態(tài)的promise既可帶著一個(gè)值成為 fulfilled 狀態(tài),也可帶著一個(gè)reason成為 rejected 狀態(tài). 任意情況發(fā)生時(shí), 通過(guò)promise的 then 方法所排列(queued up)的相應(yīng)handlers 就會(huì)被調(diào)用. (當(dāng)綁定相應(yīng)的 handler 時(shí),如果 promise 已經(jīng)處于 fulfilled 或 rejected 狀態(tài)這個(gè) handler 將會(huì)被調(diào)用, 所以在異步操作的完成和它的 handler 的綁定之間不存在競(jìng)爭(zhēng)條件.)
因?yàn)?Promise.prototype.then 和 Promise.prototype.catch 方法返回 promises, 所以它們可以被鏈?zhǔn)秸{(diào)用—一種被稱為 composition 的操作.
Promise 為何出現(xiàn)?簡(jiǎn)單的說(shuō),Promise 被當(dāng)成 callback hell 的救命仙丹。
回調(diào)函數(shù)是JavaScript的一大特色! node.js官方的api基本都是以會(huì)回調(diào)方式傳遞函數(shù)返回值。習(xí)慣同步編程的對(duì)這種異步方式多少會(huì)產(chǎn)生水土不服,而且層層嵌套,不知不覺(jué)就建造起了一座高高的回調(diào)金字塔。針對(duì)這種普遍問(wèn)題,Promise應(yīng)勢(shì)而生!
Promise 基本用法創(chuàng)建 Promise
var promise = new Promise(function(resolve, reject) { // 做一些異步操作的事情,然后…… if (/* 一切正常 */) { resolve("Stuff worked!"); } else { reject(Error("It broke")); } });
Promise 的構(gòu)造器接受一個(gè)函數(shù)作為參數(shù),它會(huì)傳遞給這個(gè)回調(diào)函數(shù)兩個(gè)變量 resolve 和 reject。在回調(diào)函數(shù)中做一些異步操作,成功之后調(diào)用 resolve,否則調(diào)用 reject。
調(diào)用 reject 的時(shí)候傳遞給它一個(gè) Error 對(duì)象只是個(gè)慣例并非必須,這和經(jīng)典 JavaScript 中的 throw 一樣。傳遞 Error 對(duì)象的好處是它包含了調(diào)用堆棧,在調(diào)試的時(shí)候會(huì)有點(diǎn)用處。
使用 Promise:
promise.then(function(result) { console.log(result); // “完美!” }, function(err) { console.log(err); // Error: "出問(wèn)題了" });
“then”接受兩個(gè)參數(shù),成功的時(shí)候調(diào)用一個(gè),失敗的時(shí)候調(diào)用另一個(gè),兩個(gè)都是可選的,所以你可以只處理成功的情況或者失敗的情況。
Promise 實(shí)踐值的處理
你可以對(duì)結(jié)果做些修改然后返回一個(gè)新值:
var promise = new Promise(function(resolve, reject) { resolve(1); }); promise.then(function(val) { console.log(val); // 1 return val + 2; }).then(function(val) { console.log(val); // 3 });
隊(duì)列的異步操作
你也可以把“then”串聯(lián)起來(lái)依次執(zhí)行異步操作。
當(dāng)你從“then”的回調(diào)函數(shù)返回的時(shí)候,這里有點(diǎn)小魔法。如果你返回一個(gè)值,它就會(huì)被傳給下一個(gè)“then”的回調(diào);而如果你返回一個(gè)“類 Promise”的對(duì)象,則下一個(gè)“then”就會(huì)等待這個(gè) Promise 明確結(jié)束(成功/失?。┎艜?huì)執(zhí)行。例如:
你也可以把“then”串聯(lián)起來(lái)依次執(zhí)行異步操作。
當(dāng)你從“then”的回調(diào)函數(shù)返回的時(shí)候,這里有點(diǎn)小魔法。如果你返回一個(gè)值,它就會(huì)被傳給下一個(gè)“then”的回調(diào);而如果你返回一個(gè)“類 Promise”的對(duì)象,則下一個(gè)“then”就會(huì)等待這個(gè) Promise 明確結(jié)束(成功/失?。┎艜?huì)執(zhí)行。例如:
返回一個(gè)值
getJSON("story.json").then(function(story) { return getJSON(story.chapterUrls[0]); }).then(function(chapter1) { console.log("Got chapter 1!", chapter1); });
你返回一個(gè)“類 Promise”的對(duì)象
var storyPromise; function getChapter(i) { storyPromise = storyPromise || getJSON("story.json"); return storyPromise.then(function(story) { return getJSON(story.chapterUrls[i]); }) } // 用起來(lái)非常簡(jiǎn)單: getChapter(0).then(function(chapter) { console.log(chapter); return getChapter(1); }).then(function(chapter) { console.log(chapter); });
錯(cuò)誤處理
前面已經(jīng)看到,“then”接受兩個(gè)參數(shù),一個(gè)處理成功,一個(gè)處理失?。ɑ蛘哒f(shuō)肯定和否定,按 Promise 術(shù)語(yǔ)):
get("story.json").then(function(response) { console.log("Success!", response); }, function(error) { console.log("Failed!", error); });
你還可以使用“catch”:
get("story.json").then(function(response) { console.log("Success!", response); }).catch(function(error) { console.log("Failed!", error); });
Promise 被否定之后會(huì)跳轉(zhuǎn)到之后第一個(gè)配置了否定回調(diào)的 then(或 catch,一樣的)。對(duì)于 then(func1, func2) 來(lái)說(shuō),必會(huì)調(diào)用 func1 或 func2 之一,但絕不會(huì)兩個(gè)都調(diào)用。而 then(func1).catch(func2) 這樣,如果 func1 返回否定的話 func2 也會(huì)被調(diào)用,因?yàn)樗麄兪擎準(zhǔn)秸{(diào)用中獨(dú)立的兩個(gè)步驟??聪旅孢@段代碼:
asyncThing1().then(function() { return asyncThing2(); }).then(function() { return asyncThing3(); }).catch(function(err) { return asyncRecovery1(); }).then(function() { return asyncThing4(); }, function(err) { return asyncRecovery2(); }).catch(function(err) { console.log("Don"t worry about it"); }).then(function() { console.log("All done!"); });Promise API 參考
靜態(tài)方法
Promise.resolve(promise);
返回一個(gè) Promise(當(dāng)且僅當(dāng) promise.constructor == Promise)
Promise.resolve(thenable);
從 thenable 對(duì)象創(chuàng)建一個(gè)新的 Promise。一個(gè) thenable(類 Promise)對(duì)象是一個(gè)帶有“then”方法的對(duì)象。
Promise.resolve(obj);
創(chuàng)建一個(gè)以 obj 為肯定結(jié)果的 Promise。
Promise.reject(obj);
創(chuàng)建一個(gè)以 obj 為否定結(jié)果的 Promise。為了一致性和調(diào)試便利(如堆棧追蹤),obj 應(yīng)該是一個(gè) Error 實(shí)例對(duì)象。
Promise.all(array);
創(chuàng)建一個(gè) Promise,當(dāng)且僅當(dāng)傳入數(shù)組中的所有 Promise 都肯定之后才肯定,如果遇到數(shù)組中的任何一個(gè) Promise 以否定結(jié)束,則拋出否定結(jié)果。每個(gè)數(shù)組元素都會(huì)首先經(jīng)過(guò) Promise.resolve,所以數(shù)組可以包含類 Promise 對(duì)象或者其他對(duì)象??隙ńY(jié)果是一個(gè)數(shù)組,包含傳入數(shù)組中每個(gè) Promise 的肯定結(jié)果(且保持順序);否定結(jié)果是傳入數(shù)組中第一個(gè)遇到的否定結(jié)果。
Promise.race(array);
創(chuàng)建一個(gè) Promise,當(dāng)數(shù)組中的任意對(duì)象肯定時(shí)將其結(jié)果作為肯定結(jié)束,或者當(dāng)數(shù)組中任意對(duì)象否定時(shí)將其結(jié)果作為否定結(jié)束。
其實(shí)已經(jīng)有一些第三方庫(kù)實(shí)現(xiàn)了 Promise 的功能:
Q
when
WinJS
RSVP.js
上面這些庫(kù)和 JavaScript 原生 Promise 都遵守一個(gè)通用的、標(biāo)準(zhǔn)化的規(guī)范:Promises/A+,jQuery 有個(gè)類似的方法叫 Deferred,但不兼容 Promises/A+ 規(guī)范,于是會(huì)有點(diǎn)小問(wèn)題,使用需謹(jǐn)慎。jQuery 還有一個(gè) Promise 類型,它其實(shí)是 Deferred 的縮減版,所以也有同樣問(wèn)題。
目前的瀏覽器已經(jīng)(部分)實(shí)現(xiàn)了 Promise。
Chrome 32、Opera 19 和 Firefox 29 以上的版本已經(jīng)默認(rèn)支持 Promise。由于是在 WebKit 內(nèi)核中所以我們有理由期待下個(gè)版本的 Safari 也會(huì)支持,并且 IE 也在不斷的開(kāi)發(fā)中。
要在這兩個(gè)瀏覽器上達(dá)到兼容標(biāo)準(zhǔn) Promise,或者在其他瀏覽器以及 Node.js 中使用 Promise,可以看看這個(gè) polyfill(gzip 之后 2K)。
相關(guān)參考http://www.html5rocks.com/zh/tutorials/es6/promises/
http://www.w3ctech.com/topic/721
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
http://www.codemud.net/~thinker/GinGin_CGI.py/show_id_doc/488
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92321.html
摘要:前端日?qǐng)?bào)精選理解的專題之偏函數(shù)譯理解事件驅(qū)動(dòng)機(jī)制游戲開(kāi)發(fā)前端面試中的常見(jiàn)的算法問(wèn)題發(fā)布中文前端頁(yè)面?zhèn)鲄⑸袏y產(chǎn)品技術(shù)刊讀基礎(chǔ)系列二之實(shí)現(xiàn)大轉(zhuǎn)盤抽獎(jiǎng)掘金指南眾成翻譯編程插入排序眾成翻譯源碼講解函數(shù)技術(shù)風(fēng)暴初體驗(yàn)個(gè)人文 2017-08-16 前端日?qǐng)?bào) 精選 理解 JavaScript 的 async/awaitJavaScript專題之偏函數(shù)[譯]理解 Node.js 事件驅(qū)動(dòng)機(jī)制Pokem...
摘要:去年年初寫(xiě)了一個(gè)擴(kuò)展十閱后,一直想寫(xiě)個(gè)十閱出來(lái),奈何懶癌后期,一直拖到最近才完成原型。這次心血來(lái)潮閑的蛋疼,想起去年年初就有所耳聞的,于是就打算用它來(lái)耍耍。使用鏈接庫(kù)在設(shè)備上運(yùn)行用來(lái)斷點(diǎn)調(diào)試地址學(xué)習(xí)資源圖圖圖 去年年初寫(xiě)了一個(gè) chrome 擴(kuò)展「十閱」后,一直想寫(xiě)個(gè)十閱 app 出來(lái),奈何懶癌后期,一直拖到最近才完成原型。 其實(shí)很早之前就已經(jīng)寫(xiě)過(guò)一個(gè) hybrid app 了,使用了...
摘要:但在后端代碼中容易識(shí)別成注釋,慎用忘記加分號(hào)啦執(zhí)行為協(xié)議,這里意思為不執(zhí)行任何命令忘記加分號(hào)啦執(zhí)行為協(xié)議,這里意思為不執(zhí)行任何命令標(biāo)簽也用于跳轉(zhuǎn)頁(yè)面,但必須有按鈕或者點(diǎn)擊才能跳轉(zhuǎn)完整樣式網(wǎng)址同標(biāo)簽提交必須寫(xiě)屬性才能被提交。 碎碎念 關(guān)于布局 css布局:橫向、縱向 2019年新進(jìn)展:css grid git bash 上安裝 http server 目的在于不使用 file:/...
摘要:但在后端代碼中容易識(shí)別成注釋,慎用忘記加分號(hào)啦執(zhí)行為協(xié)議,這里意思為不執(zhí)行任何命令忘記加分號(hào)啦執(zhí)行為協(xié)議,這里意思為不執(zhí)行任何命令標(biāo)簽也用于跳轉(zhuǎn)頁(yè)面,但必須有按鈕或者點(diǎn)擊才能跳轉(zhuǎn)完整樣式網(wǎng)址同標(biāo)簽提交必須寫(xiě)屬性才能被提交。 碎碎念 關(guān)于布局 css布局:橫向、縱向 2019年新進(jìn)展:css grid git bash 上安裝 http server 目的在于不使用 file:/...
閱讀 1830·2023-04-26 01:55
閱讀 1090·2021-09-30 09:47
閱讀 1685·2019-08-30 15:54
閱讀 750·2019-08-30 15:53
閱讀 706·2019-08-30 15:52
閱讀 1146·2019-08-30 15:44
閱讀 2421·2019-08-30 14:06
閱讀 1070·2019-08-29 16:39