你如何正确地承诺请求?
Posted
技术标签:
【中文标题】你如何正确地承诺请求?【英文标题】:How do you properly promisify request? 【发布时间】:2015-04-03 04:37:56 【问题描述】:Bluebird promisifaction 有点魔力,而request
则是一团糟(它是一个函数,其行为就像一个带有方法的对象)。
具体场景非常简单:我有一个启用了 cookie 的请求实例,通过一个 cookie jar(不使用 request
的全局 cookie 处理程序)。我怎样才能有效地承诺它,以及它支持的所有方法?
理想情况下,我希望能够:
致电request(url)
-> 承诺
致电request.getAsync(url)
-> 承诺
致电request.postAsync(url, )
-> 承诺
似乎Promise.promisifyAll(request)
无效(因为我收到“未定义 postAsync”)。
【问题讨论】:
全面披露,我是作者:http-as-promised. @idbehold 你只需要透露一些事情,如果你要说的话:P 这不是小事,请考虑在问题跟踪器上打开一个问题。request(...)
和request.get(...)
不一样吗?为什么两者都需要?
@Esailija 我猜是这样,但这主要是为了避免混淆。我想关键是所有的 API 都是承诺的,而且我没有挂起的回调,因为我没有意识到我需要它。严格来说,是的。两者之一是可选的。
【参考方案1】:
以下应该有效:
var request = Promise.promisify(require("request"));
Promise.promisifyAll(request);
请注意,这意味着 request
不是免费函数,因为 Promisification 与原型方法一起使用,因为事先不知道 this
。它仅适用于较新版本的蓝鸟。为 cookie 派生请求对象时,在需要时重复此操作。
如果您使用的是 Bluebird v3,则需要使用 multiArgs
选项:
var request = Promise.promisify(require("request"), multiArgs: true);
Promise.promisifyAll(request, multiArgs: true)
这是因为请求的回调是(err, response, body)
:Bluebird v3 的默认行为是只接受第一个成功值参数(即response
)并忽略其他参数(即body
)。
【讨论】:
request
的 cookie 是如何工作的?因为据我所知,它创建了一个 request
的新实例,其中包含一个 cookie 罐
@SecondRikudo 现在可以在新的蓝鸟中使用。请检查一下:)
当您说“较新的版本”时,具体是哪些版本?
Bluebird 的承诺对发送到request.get()
回调的response
和body
参数有什么作用?它是否忽略了正文,只使用 response
参数作为 promise 的解析值?
@Retsam 这只是multiArgs: true
,这是答案的一部分。【参考方案2】:
您可以使用request-promise 模块。
世界著名的 HTTP 客户端“请求”现在符合 Promises/A+。 由蓝鸟提供支持。
安装模块,就可以使用promise风格的request了。
npm install request-promise
【讨论】:
nit:没有 .tapCatch 或其他 bluebird 方法 它使用的不是最新版本的bluebird【参考方案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://***.com")
.then((statusCode, body) =>
//do something
);
或者,等效地使用async/await
:
const foo = async () =>
const statusCode, body = await getAsync("http://***.com")
// do something
【讨论】:
请注意,最初的问题是关于request
对象,而不是它的任何方法,那些(相对)容易。【参考方案4】:
请注意,您不需要第三个回调参数body
。它也出现在response
参数上。如果你check the source 可以看到body
只是response.body
的方便。保证它们始终相同。
这意味着本页其他答案中描述的简单承诺足以获取所有响应数据。
const request = require('request')
const promisify = require('util')
const rp = promisify(request)
rp('https://example.com').then((body, statusCode) => ...)
这仅适用于传递给回调/承诺的response
。传递给响应 event 的 response
对象是标准的 http.IncomingMessage
,因此没有 body
属性。
【讨论】:
以上是关于你如何正确地承诺请求?的主要内容,如果未能解决你的问题,请参考以下文章