承诺:跟踪匹配的输入/输出标识符

2022-04-03 00:00:00 javascript es6-promise

假设我需要通过API发出几个请求,以便在数据库中存储一些数据。每个条目在客户端都有一个唯一的标识符。但是,在远程端插入时,它将获得新的唯一标识符。这是不能更改的,即我不能强制远程端使用相同的标识符。当承诺解析时,该标识符(以及其他一些数据)被发送回客户端。跟踪所有这些信息的最佳实践是什么。

插图:

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,它接受承诺的可迭代(类似于数组),等待所有承诺都得到解决(实现或拒绝),然后以与提供给它的可迭代相同的顺序返回一个数组。然后,您可以循环访问,并应用新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]`
    }
}

下面是一个示例,其中的承诺被故意乱序处理,以证明结果数组与输入可迭代数组的顺序相同(因为您不确定是这样的):

数据-lang="js"数据-隐藏="真"数据-控制台="真"数据-巴贝尔="假">
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...
});

相关文章