首頁 > web前端 > js教程 > 主體

基於es6:非同步流程控制思想

零下一度
發布: 2017-06-26 09:10:04
原創
1388 人瀏覽過

——基於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+規範在具體的應用中的呼叫方式:

我們可以根據promise規範,將上面的例子改為:

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與Deferred, Promise負責處理函數的分發,Deferred顧名思義,處理了延遲物件。

 Promise =.queue = []; .isPromise = = handler =((fulfilledHandler) == =((errorHandler) == =  Deferred =.promise = =
登入後複製

可以看到Promise.then方法只是將回呼插入佇列,一個完成態執行,一個失敗態執行。

為了完成整個流程,還需要在Deferred中定義完成態和失敗態的處理方法:

//处理内部操作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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板