承诺:跟踪匹配 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...
});
假设我需要通过 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...
});