Chrome:不推荐在微任务执行期间调用“alert()"并将被删除 [英] Chrome: Invoking 'alert()' during microtask execution is deprecated and will be removed

查看:9
本文介绍了Chrome:不推荐在微任务执行期间调用“alert()"并将被删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在处理我的网络应用程序时,特别是文件上传,Chrome 在我调用警报后显示警告:

<块引用>

不推荐在微任务执行期间调用alert()",并将在 2016 年 9 月左右在 M53 中删除.请参阅 https://www.chromestatus.com/features/5647113010544640 了解更多详情.

然而,我认为在我的情况下,调用是合理的,并且有点担心一旦 M53 发布,我的代码将无法工作.请注意,我没有将警报交付到生产环境中,但对于测试而言,它非常有价值.

情况:

我正在使用 react 在打字稿中开发我的应用程序.我正在使用 axios 来执行 http 请求.基本上 http-post 看起来像这样:

axios.post("/upload/", data).then((响应:任何)=> {回调(未定义);}).catch((错误:任何)=> {回调(错误);});

然后在调用方法中,如果出现错误,我会弹出警报,这样我就可以确保测试人员/开发人员会收到通知.有点像这样:

this.service.uploadFile((error: any) => {如果(错误){控制台日志(错误);alert("发生错误");返回;}this.onUploadCompleted()});

这是 chrome 显示警告的时间.

首先,我想知道警告是否合理,因为直到请求完成并返回错误后才会显示警报.所以我很确定它没有阻塞任何东西.

如果它是合理的,我可以做些什么才能显示警报?

解决方案

是的,警告是有道理的:您在微任务中调用 alert,在本例中为 promise 完成.(请参阅在一个事件循环上下文.)

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

您可以通过在任务中执行alert来解决这个问题:

this.service.uploadFile((error: any) => {如果(错误){setTimeout(() => {控制台日志(错误);alert("发生错误");}, 0);返回;}this.onUploadCompleted()});

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

<小时>

这是一个有趣的微任务和宏任务示例:promise 完成是一个微任务,而定时器回调是宏任务.脚本的初始运行也是一个宏任务,就像一个 DOM 事件回调.由一个宏任务排队的所有微任务在下一个宏任务运行之前运行;例如,他们插队.所以有了这个:

//首先我们设置一个0ms的定时器回调setTimeout(() => {console.log("定时器触发");}, 0);//现在我们得到了一个 * 已经 * 解决的承诺并钩住了一个回调Promise.resolve().then(() => {console.log("承诺已解决");});//现在显示一条消息,证明我们在承诺解析回调之前到达这里console.log("到了最后");

...我们看到

<前>到了尽头承诺已解决定时器触发

...而不是

<前>到了尽头定时器触发承诺已解决

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

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?

解决方案

Yes, the warning is justified: You're calling alert within a microtask, in this case a promise completion. (See Difference between microtask and macrotask within an event loop context.)

alert, prompt, and confirm are relics of an age long past, and they have a problem: They completely interrupt the normal workings of JavaScript and arguably violate its run-to-completion semantics by completely suspending execution, right in the middle of a job from the job queue (or a task from the event loop; JavaScript and the HTML5 spec differ on terminology) and do UI in the form of a blocking modal. This is just not in keeping with the general mode of interaction, which is event-based (show the message, get an event when it's closed).

You can work around it by doing the alert in a macrotask instead:

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

    this.onUploadCompleted()
});

...but really the solution is to stop using alert, prompt, and confirm entirely.


Here's a fun example of micro and macro tasks: A promise completion is a microtask, whereas timer callbacks are macrotasks. The initial run of the script is also a macrotask, as is a DOM event callback. All of the microtasks queued by a macrotask are run before the next macrotask is run; e.g., they jump the queue. So with this:

// 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");

...we see

got to the end
promise resolved
timer fired

...rather than

got to the end
timer fired
promise resolved

....which we would have gotten if all tasks were created equal.

这篇关于Chrome:不推荐在微任务执行期间调用“alert()"并将被删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆