摘要:狀態(tài)機(jī)由于僅僅是一個狀態(tài)機(jī),我們必須從我們將會用到的狀態(tài)信息開始考慮。觀察方法我們現(xiàn)在有一個已經(jīng)完成的狀態(tài)機(jī),但是我們?nèi)匀粵]有觀察他的變化。
promise javascript 異步
這幾天在看樸靈的深入淺出nodejs,看到異步編程的解決方案這一章時,卡在了promise這個地方。心中的念頭就是自己動手寫一個promise才好,于是就開始在網(wǎng)上找資料。
簡介,這些代碼首先是發(fā)表在Stack Overflow,是希望你能從中學(xué)習(xí)如何使用javascript實現(xiàn)一個promise,你將會更好的理解promise是如何的實現(xiàn)的。
狀態(tài)機(jī)由于promise僅僅是一個狀態(tài)機(jī),我們必須從我們將會用到的狀態(tài)信息開始考慮。
var PENDDING = 0; var FULFILLED = 1; var REJECTED = 2; function Promise(){ //保存的狀態(tài)可以為PENDDING,FULFILLED和REJECTED var state = PENDDING; //一旦FULFILLED或者REJECTED保存為value或者err var value = null; //保存成功或者失敗的處理程序 var handlers = [] }轉(zhuǎn)變
第二步,讓我們考慮下面兩種可能出現(xiàn)的情形,fulfilling和rejecting:
var PENDDING = 0; var FULFILLED = 1; var REJECTED = 2; function Promise(){ //保存的狀態(tài)可以為PENDDING,FULFILLED和REJECTED var state = PENDDING; //一旦FULFILLED或者REJECTED保存為value或者err var value = null; //保存成功或者失敗的處理程序 var handlers = [] function fullfill(result){ state = FULFILLED; value = result; } function reject(error){ state = REJECTED; value = error; } }
上面這些給了我們較低等級的變換,但是我們還可以考慮額外更高級的叫做resolve的變換。
var PENDDING = 0; var FULFILLED = 1; var REJECTED = 2; function Promise(){ //保存的狀態(tài)可以為PENDDING,FULFILLED和REJECTED var state = PENDDING; //一旦FULFILLED或者REJECTED保存為value或者err var value = null; //保存成功或者失敗的處理程序 var handlers = [] function fulfill(result){ state = FULFILLED; value = result; } function reject(error){ state = REJECTED; value = error; } function resolve(result){ try{ var then = getThen(result); if(then){ doResolve(then.resolve(result),resolve,reject) return } fullfill(result) }catch(e){ reject(e) } } }
注意無論傳入resolve的是一個promise對象還是一個普通值,如果它是一個promise對象,等待他完成。一個promise對象不會進(jìn)入fulfilled狀態(tài)如果它還包含一個promise對象的話,因此我們將要暴露出的resolve函數(shù)強于內(nèi)部的fulfill。我們用到了一系列的輔助函數(shù),如下:
/** * 檢查一個value是否是一個promise對象,如果是,返回那個promise的then方法 * * @param {promise|any} value * @return {Function|null} */ function getThen(value){ var t = typeof value; if(value && (t === "object"||t === "function")){ var then = value.then; if(typeof then === "function"){ return then } } return null } /** * 創(chuàng)建一個對潛在行為的處理方法并且保證onFulfilled和onRejected只被調(diào)用一次 * 不對異步做保證 * * @param {Function} fn A resolver function that may not be trusted * @param {Function} onFulfilled * @param {Function} onRejected */ function doResolve(fn,onFulfilled,onRejected){ var done = false; try{ fn(function(value){ if(done) return done = true onFulfilled(value) },function(reason){ if(done) return done = true onRejected(reason) }) }catch(ex){ if(done) return done = true onRejected(ex) } }構(gòu)造
我們現(xiàn)在已經(jīng)完成了內(nèi)部的狀態(tài)機(jī),但同時我們還需要暴露一個處理或者觀察該promise的方法,我們來增加一個處理promise的途徑:
var PENDDING = 0; var FULFILLED = 1; var REJECTED = 2; function Promise(fn){ //保存的狀態(tài)可以為PENDDING,FULFILLED和REJECTED var state = PENDDING; //一旦FULFILLED或者REJECTED保存為value或者err var value = null; //保存成功或者失敗的處理程序 var handlers = [] function fulfill(result){ state = FULFILLED; value = result; } function reject(error){ state = REJECTED; value = error; } function resolve(result){ try{ var then = getThen(result); if(then){ doResolve(then.resolve(result),resolve,reject) return } fullfill(result) }catch(e){ reject(e) } } doResolve(fn,resolve,reject) }
如你所見,我們復(fù)用了deResolve因為我們有另一個不被信任的處理器,fn函數(shù)可以調(diào)用resolve和reject多次,甚至可以拋出異常,我們現(xiàn)在要做的是保證promise只執(zhí)行或者拒絕一次,然后不在變換為其他的狀態(tài)。
觀察(.done方法)我們現(xiàn)在有一個已經(jīng)完成的狀態(tài)機(jī),但是我們?nèi)匀粵]有觀察他的變化。我們最終要完成的是實現(xiàn).then,但是由于.done簡單很多于是我們就先實現(xiàn)它。
我們現(xiàn)在要實現(xiàn)promise.done(onFulfilled,onRejected)要滿足以下的功能:
- onFulfilled和onRejected中一個被調(diào)用
- 只被調(diào)用一次
- 在下一個tick(即.done方法返回后)時才被調(diào)用
- 它將會被調(diào)用不管promise是在我們調(diào)用.done之前或者之后被處理
var PENDDING = 0; var FULFILLED = 1; var REJECTED = 2; function Promise(fn){ //保存的狀態(tài)可以為PENDDING,FULFILLED和REJECTED var state = PENDDING; //一旦FULFILLED或者REJECTED保存為value或者err var value = null; //保存成功或者失敗的處理程序 var handlers = [] function fulfill(result){ state = FULFILLED; value = result; handlers.forEach(handle); handlers = null } function reject(error){ state = REJECTED; value = error; handlers.forEach(handle); handlers = null } function resolve(result){ try{ var then = getThen(result); if(then){ doResolve(then.resolve(result),resolve,reject) return } fullfill(result) }catch(e){ reject(e) } } function handle(handler){ if(state === PENDDING){ handlers.push(handler) }else{ if(state === FULFULLIED && typeof handler.onFulfilled === "function"){ handler.onFulfilled(value); } if(state === REJECTED && typeof handler.onRejected === "function"){ handler.onRejected(value); } } } this.done = function(onFulfilled,onRejected){ //保證異步執(zhí)行 setTimeout(function(){ handle({ onFulfilled : onFulfilled, onRejected : onRejected }) },0) } doResolve(fn,resolve,reject) }
我們得確定Promise被Resolved或者Rejected后處理程序可以得到通知,僅僅是在進(jìn)入下一個tick時做這些。
觀察(.then方法)現(xiàn)在我們已經(jīng)完成了.done方法,我們可以很類似的實現(xiàn).then方法,只是要多構(gòu)建一個Promise方法。
this.then = function(onFulfilled,onRejected){ var self = this; return new Promise(function(resolve,Reject){ return self.done(function(resolve){ if(typeof onFulfilled === "function"){ try{ resolve(onFulfilled(result)) }catch(e){ reject(e) } }else{ return resolve(result) } },function(error){ if(typeof onRejected === "function"){ try{ reject(onRejected(error)) }catch(e){ reject(e) } }else{ reject(error) } }) }) }
以上翻譯自Promise Implementing。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/85417.html
摘要:前文該系列下的前幾篇文章分別對不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實際場景和一些常見的面試題。流程調(diào)度里比較常見的一種錯誤是看似串行的寫法,可以感受一下這個例子判斷以下幾種寫法的輸出結(jié)果辨別輸出順序這類題目一般出現(xiàn)在面試題里。 前文 該系列下的前幾篇文章分別對不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實際場景和一些常見的面試題。(積累不太夠,后面想到再補) 正文 流程調(diào)度...
摘要:現(xiàn)在我們要用的重點就是我們的,這是一個能讓函數(shù)并行的,可以基于多個。非常有用啊先上一個錯誤的代碼這時候我們得到的就是數(shù)字了,而不是一個數(shù)組,這就是神奇所在。 看過 (一)的同學(xué)一定覺得這個Promise很簡單,好像沒什么可以用的地方,但是事實上,它的用處非常大啊,尤其是在nodejs上,愈加重要,雖然已經(jīng)有大量的庫實現(xiàn)了對Promise的封裝了,不過我還是更傾向用原生的node來實現(xiàn)對...
摘要:現(xiàn)在我們要用的重點就是我們的,這是一個能讓函數(shù)并行的,可以基于多個。非常有用啊先上一個錯誤的代碼這時候我們得到的就是數(shù)字了,而不是一個數(shù)組,這就是神奇所在。 看過 (一)的同學(xué)一定覺得這個Promise很簡單,好像沒什么可以用的地方,但是事實上,它的用處非常大啊,尤其是在nodejs上,愈加重要,雖然已經(jīng)有大量的庫實現(xiàn)了對Promise的封裝了,不過我還是更傾向用原生的node來實現(xiàn)對...
摘要:入門之基本用法背景在我們使用異步函數(shù)比如進(jìn)行編寫代碼,如果我們需要很多個請求不同的接口,而下一個接口需要依賴上一個接口的返回值,這樣,我們的代碼則需要在各種回調(diào)函數(shù)中嵌套,這樣一層一層地下去,就形成了回調(diào)地獄。 Promise入門之基本用法 背景 在我們使用異步函數(shù)比如ajax進(jìn)行編寫代碼,如果我們需要很多個ajax請求不同的接口,而下一個接口需要依賴上一個接口的返回值,這樣,我們的代...
摘要:周五就想寫這篇文章,但是無奈花花世界的誘惑太多就一直拖到了今天,自責(zé)遍進(jìn)入正題對象用于表示一個異步操作的最終狀態(tài)完成或失敗,以及其返回的值。 周五就想寫這篇文章,但是無奈花花世界的誘惑太多……就一直拖到了今天,自責(zé)1e4遍;進(jìn)入正題Promise: Promise 對象用于表示一個異步操作的最終狀態(tài)(完成或失敗),以及其返回的值。 上為MDNPromise的定義;ES6規(guī)定Promis...
閱讀 1579·2021-10-18 13:35
閱讀 2358·2021-10-09 09:44
閱讀 812·2021-10-08 10:05
閱讀 2706·2021-09-26 09:47
閱讀 3560·2021-09-22 15:22
閱讀 427·2019-08-29 12:24
閱讀 1992·2019-08-29 11:06
閱讀 2851·2019-08-26 12:23