如何连锁Sequelize model.create()承诺,使它们按顺序执行?

问题描述 投票:0回答:1

我在使用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中进行的,以便在调用服务和运行断言之前设置测试数据,可能会有所帮助。

javascript node.js sequelize.js
1个回答
1
投票

一旦创建了一个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);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.