我的函数(不是
async
)多次调用getUserMedia(循环中for
)。 循环退出后,我需要确保所有承诺都已解决,收集结果并为
return
执行 function
。因此,我需要确保所有承诺都在点 (C) 中解决 - 请参阅以下代码,处理其处理程序的结果,然后退出该函数。
我的代码正确吗?
我很困惑,我的程序会循环等待。
我可以处理(A)点的结果,但是如果我这样做并执行
return
,那么它将退出resolve_handler,但不会退出该函数。另一方面,如果我处理结果并执行(B)点中的
return
,那么我将无法确保所有承诺都得到解决?
那么,我该如何确保呢?
let promisesToWait = [];
for (let constraintIndex = 0; constraintIndex < constraintsArray.length; constraintIndex++) {
let curConstraints = constraintsArray[constraintIndex];
let curPromise = navigator.mediaDevices.getUserMedia(curConstraints);
promisesToWait.push(curPromise);
// process a promise returned by getUserMedia
curPromise.then(
function Resolve_GetUserMedia(stream) {
// --- there is the resolve_handler ---
} // function Resolve_GetUserMedia(stream)
,
function Reject_GetUserMedia() {
// --- there is the reject_handler ---
} // function Reject_GetUserMedia() {
);
} // for (let constraintIndex = 0,
let allPromises = Promise.allSettled(promisesToWait);
// --------- wait when all promises will be settled ---------
let finishWaiting = false;
allPromises.then( () => {/*resolve:*/ finishWaiting = true;
// ================= the point (A)
},
() => {/*resolve:*/ finishWaiting = true;}
); // then
// ====================== the point (B)
let startTime = Date.now();
let loopsCounter = 0;
while (!finishWaiting) {
loopsCounter++;
}
let finishTime = Date.now();
let waitingDuration = finishTime - startTime;
// +++ output waiting statistics +++
let msg = "Wating statistics: time (ms) = " + waitingDuration + ". Waiting loops = " + loopsCounter;
DisplayLog2Message(msg);
console.log(msg);
// ======================== the point (C)
// ----------------------------------------------------------------------------
不建议您当前使用循环等待承诺解决的方法
(while (!finishWaiting))
。它会导致事件循环阻塞,并可能导致性能不佳甚至冻结应用程序。
相反,您应该利用 Promise 的异步特性并使用
await
关键字或处理 then
块内已确定的 Promise。这是使用 async/await
: 的代码的更新版本
async function yourFunction() {
let promisesToWait = [];
for (let constraintIndex = 0; constraintIndex < constraintsArray.length; constraintIndex++) {
let curConstraints = constraintsArray[constraintIndex];
let curPromise = navigator.mediaDevices.getUserMedia(curConstraints);
promisesToWait.push(curPromise);
// Process a promise returned by getUserMedia
curPromise.then(
function Resolve_GetUserMedia(stream) {
// --- there is the resolve_handler ---
},
function Reject_GetUserMedia() {
// --- there is the reject_handler ---
}
);
}
// Wait for all promises to settle
await Promise.allSettled(promisesToWait);
// Process results or perform other actions
// This point is reached only when all promises are settled
// ================= the point (C)
// ...
// You can return something here if needed
}
// Call your function
yourFunction().then(() => {
// Any code you want to execute after all promises are settled
}).catch((error) => {
console.error("Error:", error);
});
通过使用
await Promise.allSettled(promisesToWait)
,您可以确保函数不会继续超出该点,直到所有承诺都得到解决。 then
后面的 await
块是您可以在所有承诺都解决后处理结果或执行操作的地方。此外,使用 async/await
使代码更具可读性并避免阻塞事件循环。