根据promise/deferred模式
var fs = require(‘fs’);
定义Promise对象
var Promise = function(){
this.isPromise = true;//检查then中的参数(方法)返回的是不是Promise对象
this.queue = [];//用于存放then的参数,实现队列功能
};
Promise.prototype = {
then:function (fulfilledHandler,errHandler) {
var handler = {};
if(typeof fulfilledHandler === 'function'){
handler.fulfilled = fulfilledHandler;
}
if(typeof errdHandler === 'function'){
handler.error = errHandler;
}
this.queue.push(handler);//then的作用就是将他的参数push进 Promise的queue数组中
return this;//返回Promise对象以实现链式调用then
}
};
定义Deffered对象
var Deferred = function () {
this.promise = new Promise();
};
Deferred.prototype = {
resolve:function (obj) {//resolve作用就是将Promise的queue数组中的方法 按序取出并执行
var promise = this.promise;
var handler;
while((handler = promise.queue.shift())){//先进先出
if(handler && handler.fulfilled){
var ret = handler.fulfilled(obj);
if(ret && ret.isPromise){//这里的判断很重要,若then中的方法返回的是Promise对象就像Promise对象更新为then返回的Promise,然后return,只要then中的参数返回Promise对象,则resolve的while就循环一次,这样then参数中的方法调用了resolve后才能继续向下执行,这样才能保证按顺序传递参数,相当于下一步的执行一来上一步的完成。
ret.queque = promise.queue;
this.promise = ret;//这里将新返回的promise对象引用指向最初的promise,因此程序执行期间只有一个promise对象
return;
}
}
}
},
reject:function (obj) {
var promise = this.promise;
var handler;
while((handler = promise.queue.shift())){
if(handler && handler.error){
var ret = handler.error(obj);
if(ret && ret.isPromise){
ret.queque = promise.queue;
this.promise = ret;
return;
}
}
}
},
};
下面测试,首先读取zy1.txt中的内容即为then方法的参数,
var deferred = new Deferred();
function f1(){
fs.readFile('zy1.txt','utf-8',function(err,file) {
if (err) {
deferred.reject(err);
}
if(file){
deferred.resolve(file);//只有这一步执行后才会执行第一个then中 的方法,因为第一个then中的参数返回Promise对象,所以then中的 while只执行一次就停止
}
});
return deferred.promise;
}
链式添加then方法
f1().then(function(file1){//then 的参数不执行只是push进f1返回的Promise对象 的queue数组中
console.log(file1);
fs.readFile(file1,'utf-8',function(err,file){
if (err) {
deferred.reject(err);
}
if(file){
deferred.resolve(file);//只有这一步执行后才会执行第二个then中的方 法。
}
});
return deferred.promise;
}).then(function (file2) {
console.log(file2);
});
原理分析
- 用队列存放then中的参数,当resolve时顺序执行
- 一旦检测到then中的参数返回Promise对象就立即停止执行,然后将当前deferred中的promise引用指向新的then中的参数返回Promise。