Promise的實現原理

以下是promise的簡單實現

var Deferred = function () {
  this.promise = new Promise();
};

var Promise = function () {
  this.queue = [];
  this.isPromise = true; //判斷是否返回了一個promise對象
}

Promise.prototype.then = function (fulfilledHandler,errorHandler,progressHandler) {
   var handler = {};
   if(typeof fulfilledHandler === 'function'){
     handler.fulfilled = fulfilledHandler;
   }
  if(typeof errorHandler === 'function'){
    handler.error = errorHandler;
  }
  this.queue.push(handler);
  return this;
}

//生成回調函數
Deferred.prototype.callback = function () {
   var that = this;
   return function (err,file) {
     if(err){
       return that.reject(err);
     }
     that.resolve(file);
   }
}

Deferred.prototype.resolve = function (obj) {
  var promise = this.promise;
  var handler;
  while(handler = promise.queue.shift()){
     if(handler && handler.fulfilled){
       var ret = handler.fulfilled(obj);
       if(ret &&ret.isPromise){
         ret.queue = promise.queue;
         this.promise = ret;
         return ret;
       }
     }
  }
}

Deferred.prototype.reject = function (err) {
   var promise = this.promise,handler;
   while(handler = promise.queue.shift()){
     if(handler && handler.error){
       var ret = handler.error(err);
       if(ret && ret.isPromise){
         ret.queue = promise.queue;
         this.promise = ret;
         return ;
       }
     }
   }
}

這裏我們以兩次文件讀取爲例子,以驗證該設計的可行性。這裏假設讀取第二個文件是依賴於第一個文件中的內容的,相關代碼如下:

var readFile1 = function (file,encoding) {
   var deferred = new Deferred();
    fs.readFile(file,encoding,deferred.callback());
    return deferred.promise;
}

var readFile2 = function (file,encoding) {
  var deferred = new Deferred();
  fs.readFile(file,encoding,deferred.callback());
  return deferred.promise;
}

readFile1('file1.txt','utf8').then(function (file1) {
   return readFile2(file1.trim(),'utf8');
}).then(function (file2) {
   console.log(file2);
});

要讓Promise支持鏈式執行,主要通過以下兩個步驟
(1)將所有的回調都存放在隊列中
(2)Promise完成時,逐個執行回調,一旦檢測到返回了新的Promise對象,停止執行,然後將當前
deferred對象的Promise引用改變爲新的Promise對象,並將隊列中餘下的回調轉交給它。

這裏的代碼主要用於研究Promise的執行原理,在更多細節的優化方面,Q或者when等Promise庫做得更好,實際應用時請採用這些成熟庫。

注意:Promise.prototype.then的函數實現中return this;才實現了鏈式調用,this指代的是當前promise實例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章