Promise/Deferred模式

1. Promise/Deferred模式用来干嘛的???

先看一个异步调用:

$.get('/api', {   
    success: onSuccess,   
    error: onError,   
    complete: onComplete 
}); 

在上面的异步调用中,必须严谨地设置目标。那么是否有一种先执行异步调用,延迟传递处理的方式呢?答案是Promise/Deferred模式。Promise/Deferred模式 方法允许一个异步函数阻止那些干涉(即直接修改)其内部请求的进度(progress)或状态(status)的其它代码。开发者需提供Promise (承诺)对象所需的业务处理函数,在Deferred中将事件与处理函数进行绑定。

直接看示例代码,如下:

1) 首先定义Promise模块:promise.js

// Created on 2019-12-31
var events = require('events');
var EventEmitter = events.EventEmitter;
var util = require('util');

var Promise = module.exports = function () {   
    EventEmitter.call(this); 
}; 
util.inherits(Promise, EventEmitter); 
 
Promise.prototype.then = function (fulfilledHandler, errorHandler, progressHandler) {   
    if (typeof fulfilledHandler === 'function') {     
        // 利用once()方法,保证成功回调只执行一次     
        this.once('success', fulfilledHandler);   
    }   
    if (typeof errorHandler === 'function') {     
        // 利用once()方法,保证异常回调只执行一次     
        this.once('error', errorHandler);   
    }   
    if (typeof progressHandler === 'function'){     
        this.on('progress', progressHandler);   
    }   
    return this; 
};

2) 第二步定义Deferred模块:deferred.js

// Created on 2019-12-31
var Promise = require('./promise');

var Deferred = module.exports = function () {   
    this.state = 'unfulfilled';   
    this.promise = new Promise(); // Deferred与Promise是 has a 的关系
}; 
Deferred.prototype.resolve = function (obj) {   
    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); 
}; 

3) 使用实例:test.js

// Created on 2019-12-31
var Deferred = require('./deferred');
var http = require('http');

// 使用实例
var promisify = function (res) {   
    var deferred = new Deferred();   
    var result = '';   
    res.on('data', function (chunk) {  // data ---> progress
        result += chunk;     
        deferred.progress(chunk);   
    });   
    res.on('end', function () {     // end ---> success
        deferred.resolve(result);   
    });   
    res.on('error', function (err) {     
        deferred.reject(err);       // error ---> error
    });   
    return deferred.promise; 
};

// 以http调用为例
var options = {
    hostname: "www.baidu.com",
    method: "GET"
};
var req = http.request(options, function(res){
    res.setEncoding('utf8');
    promisify(res).then(function () {
        console.log("end");
    }, function(err) {
        console.log("error:", err);
    }, function (chunk) {
        console.log("Received %s bytes", chunk.length);
    });
});
req.end();

执行结果:

Administrator@DESKTOP-MC957MJ MINGW64 /e/NodeJS/test/4_3_2
$ node test.js
Received 8610 bytes
Received 5670 bytes
end

分析:

下面直接看一下Promise/Deferred的模块关系图:

                               

理解Deferred/Promise,关键是弄明白test.js里的 promisify(res).then(...); 干了什么。我们一步步看:

 先看 promisify(res),我们定义了一个 promisify(res)函数,作用就是绑定http response的res的data、end、error事件侦听器:

res.on('data', function (chunk) {  // data ---> progress
        result += chunk;     
        deferred.progress(chunk);   
    });   
    res.on('end', function () {     // end ---> success
        deferred.resolve(result);   
    });   
    res.on('error', function (err) {     
        deferred.reject(err);       // error ---> error
    });   

然后在侦听器中emit Deferred模块的事件信号,从而绑定到Promises的progress,success,error事件侦听器。那Promise的 progress,success,error事件侦听器是什么呢?就是我们需要传入给Promise的事件Handler。即.then(...) 。代码中 (...) 为三个函数,用于响应Deferred模块的progress,success,error事件信号。因此就达到了先执行异步调用,延迟传递处理的目的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值