循环中的 Node JS Api 请求

Ola*_*son 1 loops callback request node.js

我正在尽我最大的努力避免我的 Node JS 回调地狱。但是我正在尝试发出大量 api 请求并将它们插入到我的数据库中。

我的问题(当然)是我的 for 循环在完成请求和数据库插入之前运行并增加 i 。

for(var i = 0; i <= 1 ; i++){
    apiRequest = data[i]; 
    apicall(apiRequest);
}


function apicall(urlApi){
    request((urlApi), function(error, response, body){
        if(error){
            console.log("error");
        } else if(!error && response.statusCode == 200){
            var myobj = JSON.parse(body);
            dbInsert(myobj);
        }
    });
}

function dbInsert(obj) {
    //insert into database
}
Run Code Online (Sandbox Code Playgroud)

如果其他人会问这个问题,我可以真正推荐这篇博文,这是我在阅读joshvermaire的回复后发现的:

http://www.sebastianseilund.com/nodejs-async-in-practice

jfr*_*d00 6

有多种方法可以解决此类问题。首先,如果您可以并行运行所有 API 调用(同时所有 API 调用)并且它们插入数据库中的顺序无关紧要,那么您可以通过这样做更快地获得结果(与.按顺序序列化它们)。

在以下所有选项中,您将使用以下代码:

const rp = require('request-promise');

function apicall(urlApi){
    return rp({url: urlApi, json: true}).then(function(obj){
        return dbInsert(obj);
    });
}

function dbInsert(obj) {
    //insert into database
    // return a promise that resolves when the database insertion is done
}
Run Code Online (Sandbox Code Playgroud)

并行使用 ES6 标准 Promises

let promises = [];
for (let i = 0; i <= data.length; i++) {
    promises.push(apicall(data[i]));
}

Promise.all(promises).then(() => {
    // all done here
}).catch(err => {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

并行使用 Bluebird Promise 库

使用 Bluebird Promise 库,您可以使用它Promise.map()来迭代您的数组,并且您可以将concurrency选项传递给它来控制同时进行的异步调用的数量,这可能不会使数据库或目标 API 主机不堪重负,并且可能有助于控制最大内存使用量。

Promise.map(data, apiCall, {concurrency: 10}).then(() => {
    // all done here
}).catch(err => {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

使用标准 ES6 Promise 串联

如果您出于某种原因必须序列化它们,例如按顺序插入数据库,那么您可以这样做。下面.reduce()显示的模式是使用标准 ES6 在数组上序列化 promise 操作的经典方法:

data.reduce(data, (p, item) => {
    return p.then(() => {
        return apicall(item);
    });
}, Promise.resolve()).then(() => {
    // all done here
}).catch(err => {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

串联使用 Bluebird Promise

Bluebird 有一个连续Promise.mapSeries()迭代数组,调用一个函数,该函数返回对数组中每个项目的承诺,这比手动执行要简单一些。

Promise.mapSeries(data, apiCall).then(() => {
    // all done here
}).catch(err => {
    // error here
});
Run Code Online (Sandbox Code Playgroud)