——基於es6:Promise/A+ 規格簡單實現非同步流程控制想法
nodejs強大的非同步處理能力使得它在伺服器端大放異彩,基於它的應用不斷的增加,但是異步隨之帶來的嵌套、難以理解的代碼讓nodejs看起來並沒有那麼優雅,顯得臃腫。類似於這樣的程式碼:
function println(name,callback){var value = {"ztf":"abc","abc":"def","def":1} setTimeout(function(){ callback(value[name]); },500); } println("ztf",function(name){ println(name,function(res){ console.log(res);//def println(res,function(res1){ console.log(res1);//1 }) }); });
上面的程式碼println中定義了value對象,延遲五百秒呼叫callback傳入相關的值,
先呼叫println傳入"ztf",假設下一個執行函數依賴與本次傳回的值,那麼呼叫就變成了上面的程式碼傳入ztf返回abc ,使用abc返回def,使用def返回1;
因為nodejs是作為服務端使用,必不可少的就是各種資料庫查詢,資料庫查詢擁有更多的依賴,例如我需要查詢某個使用者的權限,那麼需要三步驟
① 通過id尋找使用者
② 透過傳回的使用者角色id尋找對應的角色
③ 透過角色找到對應的權限
# 此處才需要三層嵌套關係,程式碼也需要三層嵌套關係,程式碼也需要三層嵌套關係,程式碼也需要三層嵌套關係,程式碼也需要三層巢狀關係,程式碼也需要三層巢狀關係,程式碼也需要三層巢狀關係,程式碼也需要三層巢狀關係,程式碼也會找到對應的權限
#就跟上面的差不多了。
promise/A+規格 Promise表示一個非同步運算的最終結果。它有三個狀態,分別是
未完成態、完成態(resolve)、失敗態(reject)狀態不可逆,完成態不能回傳未完成,失敗態不能變成完成態
#
與promise主要的交互方式是在它的then方法中傳入回呼函數,形成鍊式調用,
# #實作
首先我們來看Promise/A+規範在具體的應用中的呼叫方式:
var printText = function(name){var deferred = new Deferred(); //new一个托管函数println(name,deferred.callback());//把回调函数托管到Deferred中实现return deferred.promise; //返回promise对象实现链式调用} printText("ztf") .then(function(name){ console.log(name);return printText(name); //第二次调用依赖第一次调用 返回promise对象 在成功态中判断 }) .then(function(res){ console.log(res);//defreturn printText(res); }) .then(function(res1){ console.log(res1);//1});
這樣的程式碼從某種程度上,改變了非同步程式碼不斷嵌套的現狀,透過then()方法的鍊式調用,達到非同步程式碼的流程控制。
//处理回调var Promise = function(){this.queue = []; //存储的是回调函数的队列this.isPromise = true; }//延迟对象var Deferred = function(){this.promise = new Promise(); } Deferred.prototype = {//托管了callback回调函数 callback:function(){ },//完成态 resolve:function(){ },//失败态 reject:function(){ } }
Promise =.queue = []; .isPromise = = handler =((fulfilledHandler) == =((errorHandler) == = Deferred =.promise = =
可以看到Promise.then方法只是將回呼插入佇列,一個完成態執行,一個失敗態執行。
//处理内部操作var Promise = function(){this.queue = []; //存储的是回调函数的队列this.isPromise = true; } Promise.prototype = {//then方法 fulfilledHandler是完成态时执行的回调函数 errorHandler则是失败态
then:function(fulfilledHandler,errorHandler){ var handler = {}; if(typeof(fulfilledHandler) == "function"){ handler.fulfilled = fulfilledHandler; } if(typeof(errorHandler) == "function"){ handler.errored = errorHandler; } this.queue.push(handler); return this; }
Deferred =.promise = = self = promise =((handler = promise.queue.shift())){ (handler && res = handler.fulfilled.apply(self,args); (res && res.isPromise){ res.queue ==
加入了完成型操作,這段程式碼取得了.then傳入的回呼函數集合 promise.queue while依序調用,傳入目前的arguments
然後我們需要將完成態在託管回呼函數(Deferred.callback())中,按照邏輯執行:
Promise =.queue = []; .isPromise = = handler =((fulfilledHandler) == =((errorHandler) == = Deferred =.promise = = self = args = Array.prototype.slice.call(arguments); = args.concat(Array.prototype.slice.call(arguments,)); self = promise = args =((handler = promise.queue.shift())){ (handler && res = handler.fulfilled.apply(self,args); (res && res.isPromise){ res.queue ==
//处理内部操作var Promise = function(){this.queue = []; //存储的是回调函数的队列this.isPromise = true; } Promise.prototype = {//then方法 fulfilledHandler是完成态时执行的回调函数 errorHandler则是失败态 then:function(fulfilledHandler,errorHandler){var handler = {};if(typeof(fulfilledHandler) == "function"){ handler.fulfilled = fulfilledHandler; }if(typeof(errorHandler) == "function"){ handler.errored = errorHandler; }this.queue.push(handler);return this; } }//处理外部操作var Deferred = function(){this.promise = new Promise(); } Deferred.prototype = {//托管了callback回调函数 callback:function(){var self = this;var args = Array.prototype.slice.call(arguments); //将arguments转为数组return function(err){if(err){//这里是失败态 传入了error对象 self.reject.call(self,err);return; } args = args.concat(Array.prototype.slice.call(arguments,1)); //合并外部arguments 与内部arguments 去掉err//这里是完成态 console.log(args); self.resolve.apply(self,args); } },//完成态 resolve:function(){var self = this;var promise = self.promise;var args = arguments;var handler; while((handler = promise.queue.shift())){ //取出待执行队列中的第一个函数 直到全部执行完毕if(handler && handler.fulfilled){var res = handler.fulfilled.apply(self,args); //调用失败态回调函数if(res && res.isPromise){ //如果有二次嵌套 则再次执行promiseres.queue = promise.queue; self.promise = res;return; } } } },//失败态 reject:function(err){var self = this;var promise = self.promise;var args = arguments;var handler;while((handler = promise.queue.shift())){ //取出待执行队列中的第一个函数 直到全部执行完毕if(handler && handler.errored){ var res = handler.fulfilled.call(self,err); //调用完成态回调函数 } } } }
總結
① 每個操作都回傳一樣的promise對象,保證鍊式操作
② 函數函數一個參數總是error物件無報錯則null
### ③ 每個鍊式都透過then方法連接回傳promise物件再次執行###以上是基於es6:非同步流程控制思想的詳細內容。更多資訊請關注PHP中文網其他相關文章!