简体   繁体   English

在异步函数中不调用回调等效于什么?

[英]What is the equivalent of not calling a callback when inside an async function?

Before async/await, when my code used callbacks, I was able to do three things: (1) call the callback with a result, (2) call the callback with an Error, or (3) not call the callback at all. 在异步/等待之前,当我的代码使用回调时,我能够做三件事:(1)使用结果调用回调,(2)使用错误调用回调,或者(3)完全不调用回调。

Case (3) was used in situations like this: say that you have a zoom button and a user can click it to render an image at a higher resolution, and this is an async process. 情况(3)用于以下情况:假设您有一个缩放按钮,并且用户可以单击它来以更高的分辨率渲染图像,这是一个异步过程。 If the user clicks the zoom button again, then the first render is no longer relevant, and can be canceled to let the new zoom level render run. 如果用户再次单击缩放按钮,则第一个渲染不再相关,可以取消以使新的缩放级别渲染运行。 I handled this by returning from inside the function without calling the callback, eg 我通过从函数内部返回而不调用回调来处理此问题,例如

if (process.wasCanceled()) {
  return;
}
// ...
callback(someResult);

With async/await, there are only two things that you can do: return or throw. 使用async / await,您只能做两件事:返回或抛出。 Currently, I've been using throw to indicate that the operation was canceled, since returning can falsely indicate that upstream processes should keep running. 当前,我一直在使用throw指示操作已取消,因为返回可能错误地指示上游进程应继续运行。 But the problem with throwing is that all the upstream callers need to know that it's not really an error, per se, and so they may need to check the type of the error. 但是抛出的问题是,所有上游调用者本身都需要知道这实际上不是错误,因此他们可能需要检查错误的类型。

Another crazy idea I had was to create a promise that never returns. 我的另一个疯狂想法是创造一个永远不会回报的承诺。 Eg await never() , where the function is defined like this: 例如await never() ,其中函数定义如下:

async function never () {
    return new Promise(function () {});
}

That is sort of the equivalent of not calling a callback. 这相当于不调用回调。

But I don't know if that would just leak memory over and over. 但是我不知道那是否会一遍又一遍地泄漏内存。

Is there a better equivalent without the drawbacks I mentioned above? 有没有上面提到的缺点的更好的等效方法?

If absolutely necessary, you can await a promise that never returns. 如果绝对必要,您可以等待一个永远不会返回的承诺。 This is the equivalent of not calling a callback. 这相当于不调用回调。

async function never () {
    return new Promise(function () {});
}

async function op (process) {
    // ...
    if (process.wasCanceled()) await never();
    // ...
}

According to these answers, this will be garbage collected, because the returned promise is never used and there are no connections to the heap inside the promise's function argument. 根据这些答案,这将被垃圾回收,因为从不使用返回的promise,并且promise的function参数内部没有与堆的连接。

Do never resolved promises cause memory leak? 永不解决的承诺会导致内存泄漏吗?

Are JavaScript forever-pending promises bad? JavaScript永远待定的承诺是否不好?

However, this is most likely not what you want to do, since upstream callers may like to know that their operation has been canceled. 但是,这很可能不是您想要执行的操作,因为上游呼叫者可能想知道其操作已被取消。 If the operation was initiated by a user through the UI, then yes, canceling without telling the caller is probably OK, but if the operation was initiated programmatically and cancelled some other way, eg by the user, then the calling code might need to know that, so that it can try again, or clean up resources. 如果操作是由用户通过UI启动的,那么可以,在不通知调用方的情况下取消操作可能没问题,但是,如果该操作是通过编程方式启动的,并且已通过其他方式(例如,由用户取消),则调用代码可能需要知道以便它可以重试或清理资源。

For this reason, the solution is to throw an error, of a specific class so that the caller can detect that the process was cancelled. 因此,解决方案是抛出特定类的错误,以便调用者可以检测到该进程已取消。 Eg 例如

class ProcessCanceledError extends Error {
    ...
}

async function render (process) {
    while (...) {
        // do some rendering
        await delay(20);
        if (process.wasCanceled()) throw new ProcessCanceledError();
    }
}

var zoomProcess;

async function zoom () {
    let process = new Process();
    if (zoomProcess != null && !zoomProcess.isDone()) {
        zoomProcess.cancel();
    }
    try {
        await render();
    } catch (e) {
        // or you could do e.process === process
        if (e instanceof ProcessCanceledError &&
            process.wasCanceled() // make sure it was actually ours
        ) {
            // this assumes we are a top level function
            // otherwise, you would want to propagate the error to caller's caller
            return;
        }
        throw e;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM