承诺:跟踪匹配 input/output 标识符

Promises: keep track of matching input/output identifiers

假设我需要通过 API 触发多个请求,以便将一些数据存储在数据库中。每个条目在客户端都有一个唯一的标识符。但是,在远程端插入后,它将获得一个新的唯一标识符。这无法更改,即我不能强制远程端使用相同的标识符。当 Promise 解析时,这个标识符(连同一些其他数据)被发送回客户端。跟踪这一切的最佳做法是什么。

插图:

let inputValues = ["id1", "id2", "id3"];
for (val of inputValues) {
   api.insert(val).then( (result) => {
      console.log("new id:", result.id);
   });
}

最后,我想象可能有一个像

这样的关联数组
   [ "id1": "new ID for id1 from remote server",
     "id2": "new ID for id2 from remote server",
     "id3": "new ID for id3 from remote server" ]

我非常有信心我可以写出一些可以完成这项工作的东西,但那可能是充满反模式的糟糕代码。所以我更愿意先问:推荐的方法是什么?

看起来你正在并行(而不是串行)进行更新,所以你可以使用 Promise.allSettled,它接受承诺的可迭代(如数组),等待所有承诺解决(得到满足或拒绝),然后 returns 一个数组,其顺序与您提供给它的可迭代对象的顺序相同。然后您可以遍历并为成功更新应用新 ID。

像这样(在 async 函数中):

const inputValues = ["id1", "id2", "id3"];
const results = await Promise.allSettled(
    inputValues.map(value => api.insert(value))
);
// Here, `results` and `inputValues` will be parallel arrays
for (let i = 0; i < results.length; ++i) {
    const result = results[i];
    if (result.status === "fulfilled") {
        const newId = result.value.id;
        // Successful update, `newId` is the new ID for `inputValues[i]`
    }
}

这里有一个例子,promise 有意乱序,以证明结果数组与输入可迭代的顺序相同(因为您不确定情况是否如此):

const api = {
    async insert(value) {
        const delay = value === "id2" ? 1000 : 200;
        await new Promise(resolve => setTimeout(resolve, delay));
        console.log(`Fulfilling ${JSON.stringify(value)}`);
        return {
            id: `New ID for ${value}`
        };
    }
};
(async () => {
    const inputValues = ["id1", "id2", "id3"];
    const results = await Promise.allSettled(
        inputValues.map(value => api.insert(value))
    );
    // Here, `results` and `inputValues` will be parallel arrays
    for (let i = 0; i < results.length; ++i) {
        const result = results[i];
        if (result.status === "fulfilled") {
            const newId = result.value.id;
            const input = inputValues[i];
            console.log(`input value = ${JSON.stringify(input)}, newId = ${JSON.stringify(newId)}`);
        }
    }
})();

因为你可以看到,即使 "id2" 的操作比 "id1""id3" 的操作花费的时间更长,它仍然在结果中的第二位。


如果由于某种原因您无法使用 async 函数:

const inputValues = ["id1", "id2", "id3"];
Promise.allSettled(
    inputValues.map(value => api.insert(value))
)
.then(results => {
    // Here, `results` and `inputValues` will be parallel arrays
    for (let i = 0; i < results.length; ++i) {
        const result = results[i];
        if (result.status === "fulfilled") {
            const newId = result.value.id;
            // Successful update, `newId` is the new ID for `inputValues[i]`
        }
    }
})
.catch(error => {
    // ...handle/report error...
});