我正在 Node 中运行 knex 种子
,由于服务器的限制,需要对我的数据库进行批处理附加查询。我开始掌握 Promise 和 async/await 的窍门,但我很难让它在多个深度级别上工作(此时特别让我失望的是,它似乎以一种我不太理解的方式干扰批处理)。我的 seed
文件如下所示:
exports.seed = async function(knex) {
const fs = require('fs');
const _ = require('lodash');
function get_event_id(location) {
return knex('events')
.where({location: location})
.first()
.then(result => { return result['id']; })
.finally(() => { knex.destroy() })
}
function createImage(row, event_id) {
return {
name: row[4],
event_id: event_id
}
};
async function run_query(line) {
let row = line.split(',');
let event_id = await get_event_id(row[0]);
return createImage(row, event_id);
};
async function run_batch(batch) {
return Promise.all(batch.map(run_query));
}
const file = fs.readFileSync('./data.csv');
const lines = file.toString().replace(/[\r]/g, '').split('\n').slice(1,60); // skip csv header, then run first 59 lines
const batches = _.chunk(lines, 30); // set batch size
let images = await Promise.all(batches.map(run_batch));
console.log(_.flatten(images).length);
};
我的数据库一次可以处理 30 个查询。如果我在定义 lines
的行上使用 .slice(1,30)
运行单个批处理,一切都会正确解析。但是使用上面的 60 运行会给我ER_TOO_MANY_USER_CONNECTIONS:用户已经拥有超过“max_user_connections”的事件连接
。
如果我将 run_batch
的内容更改为 return batch.map(run_query)
,则脚本完成,并且它返回正确的条目数(因此它似乎正确批处理)。但 promise 仍然悬而未决。我缺少什么,有没有更优雅的方法来做到这一点?
最佳答案
在这一行中:
let images = await Promise.all(batches.map(run_batch));
您正在尝试并行运行所有批处理,这完全破坏了您的分块。
您可以使用带有 await
的常规 for
循环,而不是 .map()
,这样您就可以运行批处理,等待它完成,然后运行下一个批处理。
let allResults = [];
for (let batch of batches) {
let images = await run_batch(batch);
allResults.push(...images);
}
console.log(allResults);
<小时/>
仅供引用,您可能会受益于人们编写的任意数量的函数,这些函数用于处理同时运行的请求不超过 N 个的大型数组。这些不需要您手动将数据分成批处理。相反,它们会监视同时进行的请求数量,并启动您所需数量的请求,当一个请求完成后,它们会启动另一个请求,为您收集结果。
runN(fn, limit, cnt, options)
: Loop through an API on multiple requests
pMap(数组,fn,限制)
:Make several requests to an api that can only handle 20 at a time
rateLimitMap(array, requestsPerSec, maxInFlight, fn)
: Proper async method for max requests per second
mapConcurrent(数组,maxConcurrent,fn)
:Promise.all() consumes all my ram
Bluebird promise library 中还内置了执行此操作的功能。和 Async-promises library .
关于javascript - 在 Node 中正确批处理嵌套的 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59976352/