【问题标题】:Bluebird Request Function蓝鸟请求函数
【发布时间】:2017-01-11 00:44:13
【问题描述】:

我有一个来自这篇帖子的问题:Chaining Requests using BlueBird/ Request-Promise

我对承诺很陌生,所以请原谅我的天真。我成功地实现了这段代码:

var BPromise = require('bluebird');
var rp = require('request-promise');

BPromise.all([
  rp(optionsForRequest1),
  rp(optionsForRequest2)
])
.spread(function (responseRequest1, responseRequest2) {
  // Proceed with other calls...
})
.catch(function (err) {
  // Will be called if at least one request fails.
});

但在我的情况下,特定的 url 每次都不同。我想获取我的新 URL 数组,为每个 URL 构造选项对象,然后 rp()。

当我从字面上构造一个像这样的数组 - var freshArray =[rp({Uri1 w/options}), rp({Uri2 w/options}), etc] 并将其粘贴到上面的 .all( ) 中时 - 没有运气。我认为 rp() 的实现独立于 BPromise.all 调用?

如何将一个构造好的 promise 数组动态嵌入到上面的代码中?

【问题讨论】:

    标签: javascript promise bluebird


    【解决方案1】:

    我不太确定你想做什么,但会

    BPromise.all([optionsForRequest1, optionsForRequest2].map((url) => {
      const urlWithOptions = someFunction(url);
      return rp(urlWithOptions);
    })])
    .spread(function (responseRequest1, responseRequest2) {
        // Proceed with other calls...
    })
    .catch(function (err) {
        // Will be called if at least one request fails.
    });
    

    工作?如果是这样,您甚至可以在地图内使用(url) => rp(someFunction(url)) 缩短它

    === 编辑 ===

    • (x) => y 是一个 es6 的简写形式,大多数时候就像 function(x) { return y; }
    • (x) => { ... return y; } 是一种类似的速记方式,可让您拥有中间变量。
    • 关于 es6 的更多信息在网上 :) 像 here

    • .map 是在数组上定义的函数。它将函数应用于每个元素,因此[1, 2].map((x) => x + 1) 返回[2, 3]

    所以代码是这样的

    var urls = [optionsForRequest1, optionsForRequest2];
    var urlsWithOptions = [];
    for (var k in urls) {
      urlsWithOptions.push(someFunction(urls[k]));
    }
    
    BPromise.all(urlsWithOptions)
    ...
    

    【讨论】:

    • 谢谢吉格!这就是我想做的。你能帮我理解更多吗?选项数组应该是对象数组吗?它是否应该将 url 作为参数之一包含在内? .map() 如何知道/获取 .map(url) 中的 url?抱歉,我不明白 '(url) => rp(someFunction(url))' 中的 => 是什么意思。
    • 好的。我添加了一些说明。另外,谷歌是你最好的朋友google.com/…
    • 再次感谢吉格。有时当我完全迷路时,谷歌搜索会让人不知所措,所以我非常感谢你为我指明了正确的方向。我想我现在明白了。谢谢!
    • 酷,不用担心 :) 并且不要忘记接受其他人的答案,如果它很好
    • 永远不要使用for (var k in urls) 来迭代数组,因为它会迭代所有对象属性,而不仅仅是数组元素。
    【解决方案2】:

    如果您使用的是 Bluebird,并且您有一个任意数组要与异步操作并行处理,那么您应该使用 Bluebird 的 Promise.map(),因为它正是这种情况的快捷方式:

    var requestOptionsArray = [{...}, {...}, {...}];
    Promise.map(requestOptionsArray, function(item) {
        return rp(item);
    }).then(function(results) {
        // all results here
    }).catch(function(err) {
        // error here
    });
    

    Promise.map() 是迭代数组的快捷方式,对数组中的每个项目调用一个 Promise 生成函数,累积所有 Promise,然后调用 Promise.all() 与所有 Promise。它不是所有这些步骤,而是一步为您完成所有这些。最终结果是一个有序结果数组。这些操作都是并行运行的。

    如果你想序列化操作,你可以使用Promise.mapSeries()。如果您想控制同时运行的请求数量,您可以将{concurrency: 3} 选项传递给Promise.map()(对于不让目标服务器同时处理太多请求或避免某些情况下您可能一次请求太多会限制速率)。

    【讨论】:

    • 当你说“这些操作都是并行运行的”时,你指的是异步请求而不是映射,对吗?
    • @Guig - 正确。 Promise.map() 同步运行,并一个接一个地启动所有异步操作。这些异步操作同时都在“进行中”。当它们都完成时(稍后),将调用 .then() 处理程序。
    猜你喜欢
    • 2015-08-28
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    相关资源
    最近更新 更多