3

While working on my web app, specifically file uploads, Chrome displayed a warning after I called an alert:

Invoking 'alert()' during microtask execution is deprecated and will be removed in M53, around September 2016. See https://www.chromestatus.com/features/5647113010544640 for more details.

However I think that in my situation the call is justified and am a little worried my code won't work once M53 is released. Note that I'm not shipping to production with the alerts, but for testing it is quite valuable.

The situation:

I am developing my app in typescript using react. I'm using axios to do http requests. Basically the http-post looks like this:

axios.post("/upload/", data)
    .then((response: any) => {
        callback(undefined);
    })
    .catch((error: any) => {
        callback(error);
    });

Then in the calling method I'm popping an alert if there's an error so I can be sure the tester/developer will be notified. Kinda like this:

this.service.uploadFile((error: any) => {
    if (error) {
        console.log(error);
        alert("An error occured");
        return;
    }

    this.onUploadCompleted()
});

This is when chrome displays the warning.

First of all I'm wondering if the warning is justified, because the alert is shown until after the request is done and an error was returned. So I'm pretty sure it's not blocking anything.

If it is justified, what can be done so I can display the alert anyway?

4

1 回答 1

12

是的,警告是有道理的:你alert在一个微任务中调用,在这种情况下是一个承诺完成。(请参阅事件循环上下文中微任务和宏任务之间的区别。)

alert, prompt, 和confirm是很久以前的遗留物,它们有一个问题:它们完全中断了 JavaScript 的正常工作,并且可以说通过完全暂停执行来违反其运行到完成的语义,就在作业的中间队列(或事件循环中的任务;JavaScript 和 HTML5 规范在术语上有所不同)并以阻塞模式的形式执行 UI。这与基于事件的一般交互模式不符(显示消息,关闭时获取事件)。

您可以通过执行alert任务来解决它:

this.service.uploadFile((error: any) => {
    if (error) {
        setTimeout(() => {
            console.log(error);
            alert("An error occured");
        }, 0);
        return;
    }

    this.onUploadCompleted()
});

...但真正的解决方案是完全停止使用alert,promptconfirm


这是一个有趣的微任务和宏任务示例:承诺完成是微任务而计时器回调是宏任务。脚本的初始运行也是一个宏任务,DOM 事件回调也是如此。一个宏任务排队的所有微任务都在下一个宏任务运行之前运行;例如,他们插队。所以有了这个:

// First, we set a timer callback for 0ms
setTimeout(() => {
  console.log("timer fired");
}, 0);

// Now we get a promise that's *already* resolved and hook a callback
Promise.resolve().then(() => {
  console.log("promise resolved");
});

// Now show a message demonstrating we got here before the promise resolution callback
console.log("got to the end");

...我们看

走到了尽头
承诺已解决
计时器触发

...而不是

走到了尽头
计时器触发
承诺已解决

....如果所有任务都是平等的,我们会得到的。

于 2016-08-25T07:55:10.760 回答