承诺:跟踪匹配的输入/输出标识符
假设我需要通过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...
});
相关文章