最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to make superagent return a promise - Stack Overflow

programmeradmin1浏览0评论

I've been learning Node/Javascript, using promises from the start (I don't know how to not use promises and often wonder how others get along without them).

So I sometimes need to "promisify" simple stuff like reading a file with fs:

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

And that's been working great. Now I need to do the same with superagent, but the chaining style it uses has me stuck.

var request = require('superagent');
request.get(...).set(...).set(...).end(callback);  // stuck!

I'd like to replace the end() method (or ignore it and add a new method) with one that returns a promise. Something like this...

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!
});

This question here has all kinds of advice about adding methods to objects, but it's hard to see what is definitive. I was especially worried by this answer. Much of the advice centers around starting with the object's "class" and adding the function to .prototype. Something like this....

// 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

See my problem? I want the JS equivalent of "subclassing" the request "class" and adding a method, but since its a module, I need to treat the request class as more or less opaque.

I've been learning Node/Javascript, using promises from the start (I don't know how to not use promises and often wonder how others get along without them).

So I sometimes need to "promisify" simple stuff like reading a file with fs:

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

And that's been working great. Now I need to do the same with superagent, but the chaining style it uses has me stuck.

var request = require('superagent');
request.get(...).set(...).set(...).end(callback);  // stuck!

I'd like to replace the end() method (or ignore it and add a new method) with one that returns a promise. Something like this...

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!
});

This question here has all kinds of advice about adding methods to objects, but it's hard to see what is definitive. I was especially worried by this answer. Much of the advice centers around starting with the object's "class" and adding the function to .prototype. Something like this....

// 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

See my problem? I want the JS equivalent of "subclassing" the request "class" and adding a method, but since its a module, I need to treat the request class as more or less opaque.

Share Improve this question edited May 23, 2017 at 11:54 CommunityBot 11 silver badge asked Mar 30, 2016 at 15:18 user1272965user1272965 3,0748 gold badges32 silver badges51 bronze badges 4
  • npmjs./package/superagent-as-promised – Daniel Lizik Commented Mar 30, 2016 at 15:22
  • thanks @Daniel_L, will check that out. Just for leaning sake, is what I'm trying in the question doable? – user1272965 Commented Mar 30, 2016 at 15:29
  • stackoverflow./questions/29595449/… – Daniel Lizik Commented Mar 30, 2016 at 15:59
  • Re "this" is the problem!: How to access the correct this / context inside a callback? – Bergi Commented Mar 31, 2016 at 8:49
Add a ment  | 

1 Answer 1

Reset to default 7

First of all superagent already supports promises:

request.get(...).set(...).set(...).then(response => {
    // handle it here
});

Note that unlike regular then, the then here isn't a promise then - it rather actually invokes the request and acts lazily.

Second, what you want to do is pretty simple:

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

Here is what superagent itself does:

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);
}
发布评论

评论列表(0)

  1. 暂无评论