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