我在使用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
并行运行承诺,或者至少不能保证按顺序运行。
所以我接下来尝试了这样的方法(使用一些代码 由此可见):
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在这里做了一些cacheinglat-writing,让自己陷入了困境。我很高兴听到Sequelize中的一些方法,将整个数组交给别人插入,但这感觉有点像作弊--我不知道我是否想了解一下。何以 这是失败的。
我绝对肯定源数组是正确的。
知道这些调用是在Jest中进行的,以便在调用服务和运行断言之前设置测试数据,可能会有所帮助。
一旦创建了一个Promise,它里面的动作就会运行到结束 不管 如何等待承诺的决议。比如说
const prom1 = makeProm1();
const prom2 = makeProm2();
此时,"承诺 "已经开始,并将做任何他们应该做的事情(并行),即使你后来... ... 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
数组,所以无论你之后做什么都不会影响这些 Promises 的解析顺序。
你需要改变一下,这样你就只需要 创造 当您准备好让一个 Promise 开始执行时,也就是在前一个 Promise 执行完毕后,才开始执行。
const writeToTable = (model, rows) => {
for (const row of rows) {
await model.create(row);
}
}