浅谈Node异步编程的机制(3)
以上通过then()将回调函数存放起来,接下来就是等待success、error、progress事件被触发,实现这个功能的对象称为Deferred对象,即延迟对象。
var Deferred = function(){
this.state = 'unfulfilled';
this.promise = new Promise();
}
Deferred.prototype.resolve = function(obj){ //当异步完成后可将resolve作为回调函数,触发相关事件
this.state = 'fulfilled';
this.promise.emit('success',obj);
}
Deferred.prototype.reject = function(err){
this.state = 'failed';
this.promise.emit('error',err);
}
Deferred.prototype.progress = function(data){
this.promise.emit('progress',data)
}
因此,可以对一个典型的响应对象进行封装
res.setEncoding('utf8');
res.on('data',function(chunk){
console.log("Body:" + chunk);
})
res.on('end',function(){
//done
})
res.on('error',function(err){
//error
}
转换成
res.then(function(){
//done
},function(err){
//error
},function(chunk){
console.log('Body:' + chunk);
})
要完成上面的转换,首先需要对res对象进行封装,对data,end,error等事件进行promisify
var promisify = function(res){
var deferred = new Deferred(); //创建一个延迟对象来在res的异步完成回调中发布相关事件
var result = ''; //用来在progress中持续接收数据
res.on('data',function(chunk){ //res的异步操作,回调中发布事件
result += chunk;
deferred.progress(chunk);
})
res.on('end',function(){
deferred.resolve(result);
})
res.on('error',function(err){
deferred.reject(err);
});
return deferred.promise //返回deferred.promise,让外界不能改变deferred的状态,只能让promise的then()方法去接收外界来侦听相关事件。
}
promisify(res).then(function(){
//done
},function(err){
//error
},function(chunk){
console.log('Body:' + chunk);
})
以上,它将业务中不可变的部分封装在了Deferred中,将可变的部分交给了Promise
Promise中的多异步协作
Deferred.prototype.all = function(promises){
var count = promises.length; //记录传进的promise的个数
var that = this; //保存调用all的对象
var results = [];//存放所有promise完成的结果
promises.forEach(function(promise,i){//对promises逐个进行调用
promise.then(function(data){//每个promise成功之后,存放结果到result中,count--,直到所有promise被处理完了,才出发deferred的resolve方法,发布事件,传递结果出去
count--;
result[i] = data;
if(count === 0){
that.resolve(results);
}
},function(err){
that.reject(err);
});
});
return this.promise; //返回promise来让外界侦听这个deferred发布的事件。
}
var promise1 = readFile('foo.txt','utf-8');//这里的文件读取已经经过promise化
var promise2 = readFile('bar.txt','utf-8');
var deferred = new Deferred();
deferred.all([promise1,promise2]).thne(function(results){//promise1和promise2的then方法在deferred内部的all方法所调用,用于同步所有的promise
//TODO
},function(err){
//TODO
})
内容版权声明:除非注明,否则皆为本站原创文章。
