gpt4 book ai didi

javascript - 在异步函数中的不相关等待期间拒绝响应事件

转载 作者:行者123 更新时间:2023-11-29 18:49:24 25 4
gpt4 key购买 nike

当事件在函数内触发时,拒绝异步函数的“首选”方法是什么?

我目前通过用 Promise.race 包装每个异步操作来做到这一点:

async function exampleFunction(emitter){
let lastError;
emitter.once('error',error=>lastError=error);
function createCancellable(promise){
//cancel if any error occurred in between
if(lastError)throw new Error(lastError);

//race between the promise, and the next error occurring
let _callback;
return Promise.race([
promise,
new Promise((resolve, reject) =>{
emitter.on('error', _callback = reject);
}),
]).finally(() => {
//cleanup
if (_callback)
emitter.removeListener('error', _callback);
});
}

//actual code
await createCancellable(someAsyncFunction());
await createCancellable(anotherAsyncFunction());
}

是否有更好/更简洁的方法来做到这一点?

最佳答案

我不认为有任何其他方法可以做你想做的事,因为从根本上说你需要在每个阶段的两个 promise 之间进行竞争(eventemitter 的错误,以及你'实际上在做)。

但它可以简单得多,这可能使它更可口:

async function exampleFunction(emitter){
const pError = new Promise((_, reject) => {
emitter.once('error', reject);
});
const createCancellable = promise => Promise.race([pError, promise]);

await createCancellable(someAsyncFunction());
await createCancellable(anotherAsyncFunction());
}

将所有逻辑(对 someAsyncFunctionanotherAsyncFunction 的调用)包装在单个 async 函数中,然后与错误,但没有什么能阻止新包装器在错误发生时继续完成。所以你的个人种族方法是有道理的。


回复你的评论:

This catches any error that gets queued while sychronous code runs right?

它从下一个 await 开始执行,这对您来说可能还不够早。让我们添加一些同步代码:

async function exampleFunction(emitter){
// Start synchronous block 0
const pError = new Promise((_, reject) => {
emitter.once('error', reject);
});
const createCancellable = promise => Promise.race([pError, promise]);

// End synchronous block 0
await createCancellable(someAsyncFunction());
// Start synchronous block 1
doThis(); // All of these are synchronous, starting
doThat(); // after `someAsyncFunction`'s promise resolves
doSomethingElse(); // and before we call `anotherAsyncFunction`
// End synchronous block 1
await createCancellable(anotherAsyncFunction());
// Start synchronous block 2
doYetAnotherThing(); // This is synchronous again, starting after
keepDoingStuff(); // `anotherAsyncFunction`'s promise resolves and
okayLastThingNow(); // continuing until the end of the function
// End synchronous block 2
}

两种情况:

  1. eventemitter 的错误发生在 someAyncFunction 的处理过程中,同时它正在等待其他事情完成。调用 eventemitter 的事件回调的作业开始运行,拒绝 pError。这会立即拒绝 Promise.race 并拒绝 exampelFunction promise ; await createCancellable(someAsyncFunction()); 行之后没有代码运行。

  2. eventemitter 的错误发生在 someAsyncFunction 的 promise 解决后,同时“同步块(synchronized block) 1”正在运行。在那种情况下,同步块(synchronized block)将继续,因为不能中断同步作业来做其他事情,所以来自事件发射器的回调被放入作业队列中。然后当你执行 await 时,当前作业结束,其他作业可以运行。如果 eventemitter 的事件回调运行,它会拒绝该 promise ,因此 exampleFunction 从下一个 await 开始拒绝 — butanotherAsyncFunction 是否 被调用并开始,因为那发生在调用 Promise.race 之前。如果你想避免触发anotherAsyncFunction,你需要插入另一个await,见***评论:

    async function exampleFunction(emitter){
    // Start synchronous block 0
    const pError = new Promise((_, reject) => {
    emitter.once('error', reject);
    });
    const createCancellable = promise => Promise.race([pError, promise]);

    // End synchronous block 0
    await createCancellable(someAsyncFunction());
    // Start synchronous block 1
    doThis(); // All of these are synchronous, starting
    doThat(); // after `someAsyncFunction`'s promise resolves
    doSomethingElse(); // and before we call `anotherAsyncFunction`
    // End synchronous block 1
    await createCancellable(Promise.resolve()); // ***
    await createCancellable(anotherAsyncFunction());
    // Start synchronous block 2
    doYetAnotherThing(); // This is synchronous again, starting after
    keepDoingStuff(); // `anotherAsyncFunction`'s promise resolves and
    okayLastThingNow(); // continuing until the end of the function
    // End synchronous block 2
    }

为了更简单地处理#2,您可以将回调传递给 createCancellable 以进行调用,如下所示:

async function exampleFunction(emitter){
// Start synchronous block 0
const pError = new Promise((_, reject) => {
emitter.once('error', reject);
});
const createCancellable = (callback, ...args) => {
return Promise.race([pError, Promise.resolve()])
.then(() => Promise.race([pError, callback(...args)]));
};

// End synchronous block 0
await createCancellable(someAsyncFunction); // *** no ()
// Start synchronous block 1
doThis(); // All of these are synchronous, starting
doThat(); // after `someAsyncFunction`'s promise resolves
doSomethingElse(); // and before we call `anotherAsyncFunction`
// End synchronous block 1
await createCancellable(anotherAsyncFunction); // *** no ()
// Start synchronous block 2
doYetAnotherThing(); // This is synchronous again, starting after
keepDoingStuff(); // `anotherAsyncFunction`'s promise resolves and
okayLastThingNow(); // continuing until the end of the function
// End synchronous block 2
}

注意我们没有调用someAsyncFunctionanotherAsyncFunction,我们只是将函数传递给createCancellable 然后让它在首先检查 eventemitter 的拒绝后调用它们。

所以也许这并不比仅仅投入 await createCancellable(Promise.resolve()); 更简单。 :-)

关于javascript - 在异步函数中的不相关等待期间拒绝响应事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51860798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com