我对 Node ORM 库 Sequelize 有一个有趣的问题。我希望将此数据插入到一个空表中:
[
{ title: 'Expenditure 1', amount: 100 },
{ title: 'Expenditure 2', amount: 200 },
{ title: 'Expenditure 3', amount: 300 },
{ title: 'Expenditure 4', amount: 400 },
{ title: 'Expenditure 5', amount: 500 },
{ title: 'Expenditure 6', amount: 600 },
{ title: 'Expenditure 7', amount: 700 },
{ title: 'Expenditure 8', amount: 800 },
{ title: 'Expenditure 9', amount: 900 },
{ title: 'Expenditure 10', amount: 1000 },
{ title: 'Expenditure 11', amount: 1100 },
{ title: 'Expenditure 12', amount: 1200 },
{ title: 'Expenditure 13', amount: 1300 },
{ title: 'Expenditure 14', amount: 1400 },
{ title: 'Expenditure 15', amount: 1500 },
{ title: 'Expenditure 16', amount: 1600 },
{ title: 'Expenditure 17', amount: 1700 },
{ title: 'Expenditure 18', amount: 1800 },
{ title: 'Expenditure 19', amount: 1900 },
{ title: 'Expenditure 20', amount: 2000 }
]
正如人们所料,在一个新表中,这些将被赋予
id
值 1、2、3 等,按升序排列。所以我第一次尝试写这些是这样的: const writeToTable = (model, rows) => {
let promises = rows.map((row) => model.create(row));
return Promise.all(promises);
}
好吧,它有点工作,但行以不可预测的顺序插入,因为
Promise.all
并行运行 promise ,或者至少不保证按顺序运行它们。所以我接下来尝试了这个(使用一些代码 from this answer ):
const writeToTable = (model, rows) => {
let promises = rows.map((row) => model.create(row));
let chain;
for (let i in promises) {
if (chain) chain = chain.then(() => promises[i]);
if (!chain) chain = promises[0];
}
return chain;
}
看起来它必须按顺序运行项目,但不是 - 多次运行代码会产生不同的结果。奇怪的!
所以我接下来试试这个:
const writeToTable = async (model, rows) => {
let promises = rows.map((row) => model.create(row));
for (let promise of promises) {
await promise;
}
};
这是异步的,没有返回值,所以应该自动返回一个 Promise,一旦所有内部等待的调用都解决了就解决了。但是,不 - 我仍然偶尔会得到错误排序的行。
我可以使用什么技术来确保我的调用按顺序执行?我怀疑 Sequelize 在这里做了一些缓存/后期写入,并让自己陷入困境。我很高兴听到 Sequelize 中的方法可以将整个数组插入,但这感觉有点像作弊 - 我想知道我是否想了解为什么会失败。
我绝对确定源数组是正确的。
在调用服务和运行断言之前,了解这些调用是在 Jest 中进行以设置测试数据可能会有所帮助。
最佳答案
一旦 Promise 被创建,无论 Promise 的解析如何等待,它里面的操作都会运行到最后。例如:
const prom1 = makeProm1();
const prom2 = makeProm2();
在这一点上,Promises 已经开始,并且会做任何他们应该做的事情(并行),即使你稍后单独
await
它们:await prom1;
await prom2;
const makeProm = num => new Promise(
resolve => setTimeout(
() => {
console.log(num + ' resolving');
resolve();
},
Math.random() * 1000
)
);
(async () => {
const prom1 = makeProm(1);
const prom2 = makeProm(2);
await prom1;
await prom2;
console.log('Done');
})();
这就是你的每个片段正在做的 -
.map
立即为 rows
数组的每个项目创建一个新的 Promise,所以无论你之后做什么都不会影响这些 Promise 解析的顺序。您需要更改一些内容,以便仅在您准备好开始执行 Promise 时才创建 Promise - 也就是说,仅在前一个 Promise 完成执行之后:
const writeToTable = (model, rows) => {
for (const row of rows) {
await model.create(row);
}
}
关于javascript - 如何链接 Sequelize model.create() promise 以便它们按顺序执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61700176/