javascript - 在 Node 中,如何使用 Promise 从多个 URL 请求 JSON?

标签 javascript node.js mongodb promise bluebird

请原谅这个相当具体的问题,尽管我认为总体最终目标可能对其他人有用。

目标:使用从多个 JSON API URL 请求的数据填充 MongoDB。

简短的问题:到目前为止,我在 request-promise 方面取得了一些成功,它使用 Bluebird:

var rp = require('request-promise');
var options = {
    uri: 'http://www.bbc.co.uk/programmes/b006qsq5.json',
    headers: {
        'User-Agent': 'Request-Promise'
    },
    json: true
};

rp(options)
    .then(function (body) {
        // Mongoose allows us query db for existing PID and upsert
        var query = {pid: body.programme.pid},
            update = {
                name: body.programme.title,
                pid: body.programme.pid,
                desc: body.programme.short_synopsis
            },
            options = { upsert: true, new: true };

        // Find the document
        Programme.findOneAndUpdate(query, update, options, function(err, result) {
            if (err) return res.send(500, { error: err });
            return res.send("succesfully saved");
        });
    })
    .catch(function (err) {
        return res.send(err);
    })

但是,如果有任何一个 Promise 被拒绝,我该如何循环 URL 数组,而不会导致程序失败呢? 例如,如果任何 URL 出现错误,使用 Bluebird 就会失败。

const urls = ['http://google.be', 'http://google.uk']

Promise.map(urls, rp)
  .map((htmlOnePage, index) => {
    return htmlOnePage;
  })
  .then(console.log)
  .catch((e) => console.log('We encountered an error' + e));

由于我想向数据库写入成功的请求,并忽略那些可能无法立即响应的请求,因此我需要一些可以跳过被拒绝的 Promise 的内容,而 .all 则无法做到这一点。

长问题: 我整天都在阅读有关 Promise 的内容,这让我很头疼!但我发现了一些很好的资源,例如https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html ,其中提到了 Promise 工厂的使用。这对我的情况有用吗?我最初认为我应该发出每个请求,处理结果并将其添加到数据库中,然后继续处理下一个请求;但看到 .all 我认为我应该执行所有请求,将结果保存在数组中,并使用我的数据库保存功能循环遍历它。

我是否应该为此使用 Promise?也许我应该使用 async.js 之类的东西并连续运行我的请求。

非常感谢您的帮助或想法。

最佳答案

But how do I loop over an array of URLs, without the program failing if any of the promises are rejected?

如果您从 .catch 返回一个值而不是被拒绝的 Promise,您将返回一个已解决的 Promise

因此,您的 .then 对于每个单独的请求可能会返回一个类似的对象

{
    success: true,
    result: whateverTheResultIs
}

你的渔获返回

{
    success: false,
    error: whateverTheErrorIs
}

实际上,您不需要 success 属性,但这很方便

所以代码是 - 假设 process(url) 返回一个 Promise

Promise.map(urls, url => 
    process(url)
    .then(result => ({result, success:true}))
    .catch(error => ({error, success:false}))
)
.then(results => {
    let succeeded = results.filter(result => result.success).map(result => result.result);
    let failed = results.filter(result => !result.success).map(result => result.error);
});

或者,在 ES5 中

Promise.map(urls, function (url) {
    return process(url).then(function (result) {
        return { result: result, success: true };
    }).catch(function (error) {
        return { error: error, success: false };
    });
}).then(function (results) {
    var succeeded = results.filter(function (result) {
        return result.success;
    }).map(function (result) {
        return result.result;
    });
    var failed = results.filter(function (result) {
        return !result.success;
    }).map(function (result) {
        return result.error;
    });
});

关于javascript - 在 Node 中,如何使用 Promise 从多个 URL 请求 JSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41782724/

相关文章:

javascript - 在JavaScript中访问JS引擎日期常量的方法?

node.js - 使用express js和mongodb发布插入多个数据

mongodb - 如何在不丢失数据的情况下调整 mongodb 上限集合的大小?

javascript - 更喜欢解构——已经存在的变量

javascript - 在平板电脑和移动设备中隐藏灯箱

javascript - 尝试获取 request.body Nodejs 中的所有字段时出现异常 "Object.keys called on non-object while trying to access object"?

javascript - Webpack:./~/sqlite3/~/node-pre-gyp/lib/node-pre-gyp.js 中的错误未找到模块:错误:无法解析 'file' 或 'directory' ../package

javascript - 日历不显示

javascript - JQuery ajax DELETE 请求在 OPTIONS 阶段失败

node.js - 如何加速 MongoDB count() 查询?