2017-10-17 120 views
-2

我想我最害怕避免与我的节点JS的回调地狱。但我试图做大量的API请求,并将其插入到我的数据库中。节点中的JS Api请求循环

我的问题在这里(当然)是我的for-loop在我完成我的请求和数据库插入之前运行并递增。

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 
} 

如果其他人会来这个问题,我可以真实地建议我这篇文章,我通过joshvermaire读取响应后发现:

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

+0

查看async/await - 它们将允许您在apicall处于活动状态时暂停。 – theGleep

+0

'我'递增不应该在你的情况下造成问题。你的问题可能是别的。 –

回答

1

我建议使用类似async.each 。然后,你可以这样做:

async.each(data, function(apiRequest, cb) { 
    apicall(apiRequest, cb); 
}, function(err) { 
    // do something after all api requests have been made 
}); 

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

function dbInsert(obj, cb) { 
    doDBInsert(obj, cb); 
} 

dbInsert方法完成,确保cb回调被调用。如果您需要一系列操作,请参阅async.eachSeries

+0

这将如何解决用户的问题?用户的问题究竟是什么? –

1

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

在下面的所有选项,你可以使用此代码:

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 
} 

并行使用ES6标准少辉

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 
}); 

使用蓝鸟无极图书馆

随着并行蓝鸟诺言库,你可以使用Promise.map()迭代你的数组,你可以传递concurrency选项来控制同时有多少个异步调用正在运行,这可能会使数据库或目标API主机不堪重负,并可能有助于控制最大内存使用量。

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

在系列采用标准ES6少辉

如果你有连载他们出于某种原因,如为了插入数据库,那么你就可以是这样做的。下面显示的.reduce()模式是使用标准ES6阵列上连载的承诺操作的经典方式:

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

使用串联的蓝鸟公司承诺

蓝鸟有Promise.mapSeries()迭代访问串联数组,调用一个函数在数组中的每个项目上返回一个promise,这比手动操作要简单一点。

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