使用 JavaScript Promise All - 这个语法有效吗?

Using JavaScript Promise All - is this syntax valid?

我有两个 table 用户,其中一个用户的每个 ID 在两个 table 中都是相同的(不要问为什么我有两个用户 table) . 在某些时候,我需要从 table 1 中过滤用户,如果某些条件为真,我将每个用户的承诺(删除请求)存储到(我们称之为)tableOnePromises 中。我对 table 2 做同样的事情。 为了清空 table 2,由于某些要求,我必须先清空 table 一个。 这就是我所做的:

let tableOnePromises = [];
let tableTwoPromises = [];

tableOne.forEach(item => {
  if(item.deactivated) {
    const tableOneDeleted = supabase
      .from("table-one")
      .delete()
      .match({id: item.id});

    tableOnePromises.push(tableOneDeleted);

    const tableTwoDeleted = supabase
      .from("table-two")
      .delete()
      .match({id: item.id});

    tableOnePromises.push(tableTwoDeleted);
  }
});

await Promise.all(tableOnePromises).then(() => {
  return Promise.all(tableTwoPromises)
}).catch(err => console.log(err));

假设使用 await 的代码在 async 函数内(或在模块的顶层),语法 是正确的,但是它可能不是我要使用的(一般来说,避免将 async/await 与通过 .then.catch 的显式回调混合使用),并且单独它可能无法正常工作您期望的(这可以通过您说您的代码无法从 table-two 中删除来证实)。

对于任何特定的 id 值,您的代码开始从 table-one 中删除,然后 立即 开始从 table-two 中删除而不等待删除 table-one 完成:

// STARTS the deletion but doesn't wait for it to finish
const tableOneDeleted = supabase
  .from("table-one")
  .delete()
  .match({id: item.id});
// ...
// Starts deleting from `table-two`, even though the item may still be in `table-one`
const tableTwoDeleted = supabase
  .from("table-two")
  .delete()
  .match({id: item.id});

请记住,承诺只是观察异步过程的一种方式;当你得到承诺时,它所观察的过程已经在进行中。因此,即使你没有等到 table-two 承诺,你也会立即开始 table-two 删除。

...I MUST first empty table one due to some requirements...

如果说“空”,您的意思只是您必须确保在 table-one 上完成特定 iddelete,然后再在 [=20= 上完成],需要等待table-one删除完成后才能开始table-two删除。我会把它放在一个函数中:

async function deleteItem(id) {
    await supabase
        .from("table-one")
        .delete()
        .match({id});
    await supabase
        .from("table-two")
        .delete()
        .match({id});
}

那么代码就变成了:

const promises = [];
for (const {deactivated, id} of tableOne) {
    if (deactivated) {
        promises.push(deleteItem(id));
    }
}
await Promise.all(promises); // With the `try`/`catch` if desired

...或者如果可以两次遍历数组:

await Promise.all( // With the `try`/`catch` if desired
    tableOne.filter(({deactivated}) => deactivated)
            .map(({id}) => deleteItem(id))
);

¹ “...当您得到承诺时,它正在观察的过程已经在进行中。” 这是正常情况。不幸的是,有一个流行的文档 DB 库没有开始它的工作 until/unless 你称之为 then 的承诺。但这是一个例外,anti-pattern.