我对节点很新,而且我一直在学习和处理异步/承诺。现在我尝试创建一个从DB(例如10K行)插入的进程,调用一个Web服务来转换一个列,然后插入修改后的数据。
所以,我做了一个Oracle SQL查询,为了结果,我做了一个foreach:
let counter = 0;
var binds = [];
res.rows.forEach((row) => {
var original_data = row[0];
Transform(original_data).then(new_data => {
counter++;
binds.push([original_data,new_data]);
if (counter % 1000 === 0){
console.log(`1K rows`);
doInserts(binds);
binds = [];
}
});
});
我每1000行调用一次doInserts
,所以我不会在Oracle上打开很多交易。
Transform函数调用webservice,它使用我需要的值解析。
function Transform(value){
return new Promise(function(resolve, reject){
var requestPath = `http://localhost:3000/transform/${value}`;
var req = request.get(requestPath, function(err, response, body){
if (!err && response.statusCode == 200){
resolve(body);
}else{
reject("API didn't respond.");
}
}).end();
});
}
然而,当foreach有10K行时,这会阻塞web服务(我使用request库来连接)。我在想,foreach并没有同时进行一次变换。
这可能是我不知道很多节点,异步,承诺..但我很困惑。有人可以帮忙吗?
答案 0 :(得分:3)
你正在同时做很多要求。尝试设置一个并发。您可以使用蓝鸟的Promise.map:http://bluebirdjs.com/docs/api/promise.map.html
await Promise.map(rows, async (row) => {
const new_data = await Transform(row[0])
...
}, {concurrency: 3}) // allow max 3 request at the same time
答案 1 :(得分:0)
您可以使用任何承诺库或ES6 Promise来收集一系列承诺并一起解决它们。
在此示例中,我将使用bluebird
Promise.all
请注意{{1}}将尝试并行解析数组中的所有promise。如果您的数据库有连接数限制,则某些调用可能会失败。
答案 2 :(得分:0)
如果一个失败并且所有成功都失败了(如果最后一个拒绝你丢失了除最后一个结果之外的所有成功),则所选答案会拒绝。
这是适合您情况的代码,可以找到有关代码的更多信息here它不使用bluebird但使用lib.throttle(来自lib,其中包含我写的一般有用的函数)
//lib comes from: https://github.com/amsterdamharu/lib/blob/master/src/index.js
const lib = require("lib");
const Fail = function(reason){this.reason=reason;};
const isFail = o=>(o&&o.constructor)===Fail;
const isNotFail = o=>!isFail(o);
const handleBatch = results =>{//this will handle results of a batch
//failed are the requests that failed
//you may want to save the ones that failed to file or something
const failed = results.filter(isFail);
const successes = results.filter(result=>!isFail(result));
return doInserts(successes);
};
const processor = throttler => row =>
throttler(//throttling Transform to max 10 active
row=>
Transform(row[0])
.then(new_data =>[row[0],new_data])
)(row)
.catch(err=>new Fail([err,row]))//catch reject and resolve with fail object
;
//start the process
lib.batchProcess (handleBatch) (1000) (processor(lib.throttle(10))) ([]) (res.rows)
.then(
results=>console.log("Process done")
,err=>console.error("This should not happen:".err)
);