摘要:異步常用的幾種方式今天著重來講解一下和隊(duì)列有何關(guān)聯(lián)在這里我們需要先理解在應(yīng)用的過程中需要注意的地方一定要,或者出去不要,做副作用函數(shù)。拋出同步異常談到,這是讓更加贊的一點(diǎn)。再強(qiáng)調(diào)一次,這個(gè)函數(shù)并不需要關(guān)心這個(gè)異常是同步還是異步返回的。
異步常用的幾種方式
setTimeout/EventEmitter/Promise/generator/async-await 今天著重來講解一下 promise
setTimeout和Promise隊(duì)列有何關(guān)聯(lián)setTimeout(function(){console.log(4)},0); new Promise(function(resolve){ console.log(1) for( var i=0 ; i<10000 ; i++ ){ i==9999 && resolve() } console.log(2) }) .then(function(){ console.log(5) }); console.log(3);在這里我們需要先理解We have a problem with promises
doSomething().then(function () { return doSomethingElse(); }); doSomething().then(function () { doSomethingElse(); }); doSomething().then(doSomethingElse()); doSomething().then(doSomethingElse);promise 在應(yīng)用的過程中需要注意的地方
1.new promise (resolve,reject){};一定要resolve,或者reject 出去不要,做副作用函數(shù)。 2.then 操作里面 接收 promise 對象,如果在promise里面是執(zhí)行的純函數(shù),也可以返回一個(gè) promise。resolve("常量")。避免promise 穿透正確使用 promise 金字塔代碼
新手錯(cuò)誤 #1: promise版的金字塔問題
觀察大家如何使用 PouchDB 這類大型的 promise 風(fēng)格的API,我發(fā)現(xiàn)大量錯(cuò)誤的 promise 使用形式。最常見的錯(cuò)誤就是下面這個(gè):
remotedb.allDocs({ include_docs: true, attachments: true }).then(function (result) { var docs = result.rows; docs.forEach(function(element) { localdb.put(element.doc).then(function(response) { alert("Pulled doc with id " + element.doc._id + " and added to local db."); }).catch(function (err) { if (err.status == 409) { localdb.get(element.doc._id).then(function (resp) { localdb.remove(resp._id, resp._rev).then(function (resp) {
// et cetera...
是的,實(shí)際上你可以像使用回調(diào)一樣使用 promises,恩,就像用打磨機(jī)去削腳趾甲一樣,你確實(shí)可以這么做。
并且如果你以為這樣的錯(cuò)誤只限于初學(xué)者,那么你會驚訝于我實(shí)際上是在黑莓官方開發(fā)者博客上看到上面的代碼。老的回調(diào)風(fēng)格的習(xí)慣難以消滅。(至開發(fā)者: 抱歉選了你的例子,但是你的例子將會有積極的教育意義)
正確的風(fēng)格應(yīng)該是這樣:
remotedb.allDocs(...).then(function (resultOfAllDocs) { return localdb.put(...); }).then(function (resultOfPut) { return localdb.get(...); }).then(function (resultOfGet) { return localdb.put(...); }).catch(function (err) { console.log(err); });
這種寫法被稱為 composing promises ,是 promises 的強(qiáng)大能力之一。每一個(gè)函數(shù)只會在前一個(gè) promise 被調(diào)用并且完成回調(diào)后調(diào)用,并且這個(gè)函數(shù)會被前一個(gè) promise 的輸出調(diào)用,稍后我們在這塊做更多的討論。
4.promise 中foreach 操作,轉(zhuǎn)換成 promise.all()=>返回一個(gè)數(shù)組
5.在任何應(yīng)用到了promise的過程中,一定要注意使用catch 將異常拋出來,不然會堵塞整個(gè)加載
使用副作用調(diào)用而非返回下面的代碼有什么問題?
somePromise().then(function () { someOtherPromise(); }).then(function () { // Gee, I hope someOtherPromise() has resolved! // Spoiler alert: it hasn"t. });
好了,現(xiàn)在是時(shí)候討論一下關(guān)于 promises 你所需要知道的一切。
認(rèn)真的說,這是一個(gè)一旦你理解了它,就會避免所有我提及的錯(cuò)誤的古怪的技巧。你準(zhǔn)備好了么?
就如我前面所說,promises 的奇妙在于給予我們以前的 return 與 throw。但是在實(shí)踐中這到底是怎么一回事呢?
每一個(gè) promise 都會提供給你一個(gè) then() 函數(shù) (或是 catch(),實(shí)際上只是 then(null, ...) 的語法糖)。當(dāng)我們在 then() 函數(shù)內(nèi)部時(shí):
somePromise().then(function () { // I"m inside a then() function! });
我們可以做什么呢?有三種事情:
return 另一個(gè) promise
return 一個(gè)同步的值 (或者 undefined)
throw 一個(gè)同步異常
就是這樣。一旦你理解了這個(gè)技巧,你就理解了 promises。因此讓我們逐個(gè)了解下。
返回另一個(gè) promise
這是一個(gè)在 promise 文檔中常見的使用模式,也就是我們在上文中提到的 “composing promises”:
getUserByName("nolan").then(function (user) { return getUserAccountById(user.id); }).then(function (userAccount) { // I got a user account! });
注意到我是 return 第二個(gè) promise,這個(gè) return 非常重要。如果我沒有寫 return,getUserAccountById() 就會成為一個(gè)副作用,并且下一個(gè)函數(shù)將會接收到 undefined 而非 userAccount。
返回一個(gè)同步值 (或者 undefined)
返回 undefined 通常是錯(cuò)誤的,但是返回一個(gè)同步值實(shí)際上是將同步代碼包裹為 promise 風(fēng)格代碼的一種非常贊的手段。舉例來說,我們對 users 信息有一個(gè)內(nèi)存緩存。我們可以這樣做:
getUserByName("nolan").then(function (user) { if (inMemoryCache[user.id]) { return inMemoryCache[user.id]; // returning a synchronous value! } return getUserAccountById(user.id); // returning a promise! }).then(function (userAccount) { // I got a user account! });
是不是很贊?第二個(gè)函數(shù)不需要關(guān)心 userAccount 是從同步方法還是異步方法中獲取的,并且第一個(gè)函數(shù)可以非常自由的返回一個(gè)同步或者異步值。
不幸的是,有一個(gè)不便的現(xiàn)實(shí)是在 JavaScript 中無返回值函數(shù)在技術(shù)上是返回 undefined,這就意味著當(dāng)你本意是返回某些值時(shí),你很容易會不經(jīng)意間引入副作用。
出于這個(gè)原因,我個(gè)人養(yǎng)成了在 then() 函數(shù)內(nèi)部 永遠(yuǎn)返回或拋出 的習(xí)慣。我建議你也這樣做。
拋出同步異常
談到 throw,這是讓 promises 更加贊的一點(diǎn)。比如我們希望在用戶已經(jīng)登出時(shí),拋出一個(gè)同步異常。這會非常簡單:
getUserByName("nolan").then(function (user) { if (user.isLoggedOut()) { throw new Error("user logged out!"); // throwing a synchronous error! } if (inMemoryCache[user.id]) { return inMemoryCache[user.id]; // returning a synchronous value! } return getUserAccountById(user.id); // returning a promise! }).then(function (userAccount) { // I got a user account! }).catch(function (err) { // Boo, I got an error! });
如果用戶已經(jīng)登出,我們的 catch() 會接收到一個(gè)同步異常,并且如果 后續(xù)的 promise 中出現(xiàn)異步異常,他也會接收到。再強(qiáng)調(diào)一次,這個(gè)函數(shù)并不需要關(guān)心這個(gè)異常是同步還是異步返回的。
這種特性非常有用,因此它能夠在開發(fā)過程中幫助定位代碼問題。舉例來說,如果在 then() 函數(shù)內(nèi)部中的任何地方,我們執(zhí)行 JSON.parse(),如果 JSON 格式是錯(cuò)誤的,那么它就會拋出一個(gè)異常。如果是使用回調(diào)風(fēng)格,這個(gè)錯(cuò)誤很可能就會被吃掉,但是使用 promises,我們可以輕易的在 catch() 函數(shù)中處理它了。
一定要注意我們在then 函數(shù)內(nèi)部的時(shí)候我們可以做什么呢?有三種事情:
return 另一個(gè) promise
return 一個(gè)同步的值 (或者 undefined)
throw 一個(gè)同步異常
參考資料
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107627.html
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:當(dāng)引擎開始執(zhí)行一個(gè)函數(shù)比如回調(diào)函數(shù)時(shí),它就會把這個(gè)函數(shù)執(zhí)行完,也就是說只有執(zhí)行完這段代碼才會繼續(xù)執(zhí)行后面的代碼。當(dāng)條件允許時(shí),回調(diào)函數(shù)就會被運(yùn)行。現(xiàn)在,返回去執(zhí)行注冊的那個(gè)回調(diào)函數(shù)。 原文地址:http://blog.getify.com/promis... 在微博上看到有人分享LabJS作者寫的關(guān)于Promise的博客,看了下覺得寫得很好,分五個(gè)部分講解了Promise的來龍去脈。從...
摘要:深入理解引擎的執(zhí)行機(jī)制最近在反省,很多知識都是只會用,不理解底層的知識。在閱讀之前,請先記住兩點(diǎn)是單線程語言的是的執(zhí)行機(jī)制。所以,是存在異步執(zhí)行的,比如單線程是怎么實(shí)現(xiàn)異步的場景描述通過事件循環(huán),所以說,理解了機(jī)制,也就理解了的執(zhí)行機(jī)制啦。 深入理解js引擎的執(zhí)行機(jī)制 最近在反省,很多知識都是只會用,不理解底層的知識。所以在開發(fā)過程中遇到一些奇怪的比較難解決的bug,在思考的時(shí)候就會收...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個(gè)符合規(guī)范并可配合使用的寫一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過...
摘要:回調(diào)函數(shù)模式類似于事件模型,因?yàn)楫惒酱a也會在后面的一個(gè)時(shí)間點(diǎn)才執(zhí)行如果回調(diào)過多,會陷入回調(diào)地獄基礎(chǔ)可以當(dāng)做是一個(gè)占位符,表示異步操作的執(zhí)行結(jié)果。函數(shù)可以返回一個(gè),而不必訂閱一個(gè)事件或者向函數(shù)傳遞一個(gè)回調(diào)函數(shù)。 主要知識點(diǎn):Promise生命周期、Promise基本操作、Promise鏈、響應(yīng)多個(gè)Promise以及集成PromiseshowImg(https://segmentfaul...
閱讀 2993·2021-10-13 09:39
閱讀 2694·2021-09-27 13:34
閱讀 2031·2019-08-30 15:55
閱讀 3260·2019-08-30 15:43
閱讀 3631·2019-08-30 11:16
閱讀 1748·2019-08-26 18:28
閱讀 1283·2019-08-26 13:56
閱讀 914·2019-08-26 13:35