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.
SuperAgent's request is a "thenable" object that's compatible with JavaScript promises and the async / await syntax. If you're using promises, do not call .end () or .pipe (). Any use of .then () or await disables all other ways of using the request. Libraries like co or a web framework like koa can yield on any SuperAgent method:
to call Promise.resolve with 1 to return a promise that resolves to 1. Then we use the await keyword to get the resolved value and assign that to d. Therefore, d is 1. To make a promise return the resolved value instead of [object Promise] with JavaScript, we can use the await keyword.
Since most people are consumers of already-created promises, this guide will explain consumption of returned promises before explaining how to create them. Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.
This happens because after making a call to getResult method, it in turns calls the getPromise method which gets resolved only after 2000 ms. getResult method doesn’t wait since it doesn’t returns a promise. So, if you return a promise from getResult method it can then be used to wait for the Promise to get resolved.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With