Как вы должным образом обещаете запрос?
Продвижение Bluebird - немного волшебство, а request
- довольно беспорядок (это функция, которая ведет себя как объект со способами).
Конкретный сценарий довольно прост: у меня есть экземпляр запроса с включенными cookie через банку cookie (не используя request
global cookie handler). Как я могу эффективно обещать его и все методы, которые он поддерживает?
В идеале я хотел бы иметь возможность:
- вызов
request(url)
→ Обещание
- вызов
request.getAsync(url)
→ Обещание
- вызов
request.postAsync(url, {})
→ Обещание
Кажется, что Promise.promisifyAll(request)
неэффективен (поскольку я получаю "postAsync не определен" ).
Ответы
Ответ 1
Следующее должно работать:
var request = Promise.promisify(require("request"));
Promise.promisifyAll(request);
Обратите внимание, что это означает, что request
не является свободной функцией, так как promisification работает с прототипами, так как this
не известно заранее. Он будет работать только в более новых версиях bluebird. Повторите это, когда вам нужно, когда вы накладываете объект запроса на файлы cookie.
Если вы используете Bluebird v3, вам нужно использовать опцию multiArgs
:
var request = Promise.promisify(require("request"), {multiArgs: true});
Promise.promisifyAll(request, {multiArgs: true})
Это связано с тем, что обратный вызов для запроса (err, response, body)
: поведение Bluebird v3 по умолчанию должно принимать только первый аргумент значения успеха (т.е. response
) и игнорировать другие (т.е. body
).
Ответ 2
вы можете использовать модуль request-promise.
Всемирно известный HTTP-клиент "Запрос" теперь Promises/A+. Работает на Bluebird.
Установите модуль, и вы можете использовать запрос в стиле обещаний.
npm install request-promise
Ответ 3
Я приведу пример, с помощью util
базы на 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
});
Или, эквивалентно используя async/await
:
const foo = async () => {
const {statusCode, body} = await getAsync("http://stackoverflow.com")
// do something
}
Ответ 4
Обратите внимание, что вам не нужен третий параметр обратного вызова, body
. Он также присутствует в параметре response
. Если проверить источник вы можете видеть, что body
это просто удобство для response.body
. Они гарантированно всегда будут одинаковыми.
Это означает, что простого обещания, описанного в других ответах на этой странице, достаточно, чтобы получить все данные ответов.
const request = require('request')
const { promisify } = require('util')
const rp = promisify(request)
rp('https://example.com').then(({body, statusCode}) => ...)
Это верно только для response
переданного на обратный вызов/обещание. Объект response
передаваемый в событие ответа, является стандартным http.IncomingMessage
и поэтому не имеет свойства body
.