Madara's Ghost
Madara's Ghost

Reputation: 174977

How do you properly promisify request?

Bluebird promisifaction is a little magic, and request is quite a mess (it's a function which behaves as an object with methods).

The specific scenario is quite simple: I have a request instance with cookies enabled, via a cookie jar (not using request's global cookie handler). How can I effectively promisify it, and all of the methods it supports?

Ideally, I'd like to be able to:

It seems as though Promise.promisifyAll(request) is ineffective (as I'm getting "postAsync is not defined").

Upvotes: 32

Views: 39907

Answers (4)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276306

The following should work:

var request = Promise.promisify(require("request"));
Promise.promisifyAll(request);

Note that this means that request is not a free function since promisification works with prototype methods since the this isn't known in advance. It will only work in newer versions of bluebird. Repeat it when you need to when forking the request object for cookies.


If you're using Bluebird v3, you'll want to use the multiArgs option:

var request = Promise.promisify(require("request"), {multiArgs: true});
Promise.promisifyAll(request, {multiArgs: true})

This is because the callback for request is (err, response, body): the default behavior of Bluebird v3 is to only take the first success value argument (i.e. response) and to ignore the others (i.e. body).

Upvotes: 37

Tamlyn
Tamlyn

Reputation: 23562

Note that you don't need the third callback parameter, body. It is also present on the response parameter. If you check the source you can see that body is just a convenience for response.body. They are guaranteed to always be the same.

This means that simple promisification as described in other answers on this page is enough to get all response data.

const request = require('request')
const { promisify } = require('util')
const rp = promisify(request)

rp('https://example.com').then(({body, statusCode}) => ...)

This is only true of the response passed to the callback/promise. The response object passed to the response event is a standard http.IncomingMessage and as such has no body property.

Upvotes: 12

Little Roys
Little Roys

Reputation: 5779

I give an example, by util base on Node.js v11.10.0

import { get, post } from "request";
import { promisify } from "util";

const [getAsync, postAsync] = [get, post].map(promisify);


getAsync("http://stackoverflow.com")
    .then(({statusCode, body}) => { 
       //do something 
     });

Or, equivalently using async/await:

const foo = async () => {
    const {statusCode, body} = await getAsync("http://stackoverflow.com")
    // do something
}

Upvotes: 9

Arvind Sridharan
Arvind Sridharan

Reputation: 4045

you can use the request-promise module.

The world-famous HTTP client "Request" now Promises/A+ compliant. Powered by Bluebird.

Install the module and you can use request in promise style.

npm install request-promise

Upvotes: 33

Related Questions