如何让superagent回报承诺

use*_*965 4 javascript node.js promise superagent

我一直在学习Node/Javascript,从一开始就使用promises(我不知道如何使用promises,并且常常想知道其他人如何在没有它们的情况下相处).

因此,我有时需要"宣传"简单的内容,例如阅读文件fs:

var readFile = function(path) {
    return new Promise(function(fulfill, reject) {
        fs.readFile(path, function(err, data) {
            if (err) { reject(err); }
            else { fulfill(data); }
        });
    });
};
Run Code Online (Sandbox Code Playgroud)

这一直很有效.现在我需要做同样的事情superagent,但它使用的链式风格让我陷入困境.

var request = require('superagent');
request.get(...).set(...).set(...).end(callback);  // stuck!
Run Code Online (Sandbox Code Playgroud)

我想end()用一个返回promise 的方法替换方法(或忽略它并添加一个新方法).像这样......

var endQ = function() {
    return new Promise(function(fulfill, reject) {
        this.end(function(err, res) {     // "this" is the problem!
            if (err) { reject(err); }
            else { fulfill(res); }
        });
    });
};

// then I could say this:
request.get(...).set(...).set(...).endQ().then(function(res) {
    // happiness
}).catch(function(err) {
    // sad about the error, but so happy about the promise!
});
Run Code Online (Sandbox Code Playgroud)

这里的这个问题有关于向对象添加方法的各种建议,但很难看出什么是确定的.我特别担心这个答案.大多数建议都围绕着从对象的"类"开始并添加函数.prototype.像这样......

// this part doesn't make sense
var requestInstance = new Request();   // no such thing in request as far as I know
requestInstance.prototype.endQ = endQ; // would be great, but no
Run Code Online (Sandbox Code Playgroud)

看到我的问题?我希望JS等同于"子类化"请求"类"并添加一个方法,但由于它是一个模块,我需要将请求类视为或多或少不透明.

Ben*_*aum 5

首先,superagent已经支持承诺:

request.get(...).set(...).set(...).then(response => {
    // handle it here
});
Run Code Online (Sandbox Code Playgroud)

请注意,与常规不同then,then这里不是承诺 - 它实际上是调用请求并且懒惰地行动.

其次,你想要做的很简单:

Object.getPrototypeOf(request.get(...)).endQ = function() { // get to prototype and define
  /* your code here */
};
Run Code Online (Sandbox Code Playgroud)

这是superagent本身的作用:

exports.then = function then(resolve, reject) {
  if (!this._fullfilledPromise) {
    var self = this;
    this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
      self.end(function(err, res){
        if (err) innerReject(err); else innerResolve(res);
      });
    });
  }
  return this._fullfilledPromise.then(resolve, reject);
}
Run Code Online (Sandbox Code Playgroud)