Javascript async Wait在浏览器中真的是非阻塞的吗?
我一直在使用TypeScript和本机承诺在SPA中使用该功能,我注意到即使我将长期运行的函数重构为返回承诺的异步函数,UI仍然没有响应 因此,我的问题是:Javascript async Wait在浏览器中真的是非阻塞的吗?,javascript,user-interface,asynchronous,async-await,ecmascript-2017,Javascript,User Interface,Asynchronous,Async Await,Ecmascript 2017,我一直在使用TypeScript和本机承诺在SPA中使用该功能,我注意到即使我将长期运行的函数重构为返回承诺的异步函数,UI仍然没有响应 因此,我的问题是: 新的async/await功能如何帮助避免阻塞浏览器中的UI?在使用async/await实际获得响应UI时,是否需要采取任何特殊的额外步骤 有人可以创建一个提琴来演示async/Wait如何帮助用户界面响应吗 async/await与以前的异步功能(如setTimeout和XmlHttpRequest)有何关联 异步是构造异步代码的一种
- 新的async/await功能如何帮助避免阻塞浏览器中的UI?在使用async/await实际获得响应UI时,是否需要采取任何特殊的额外步骤
- 有人可以创建一个提琴来演示async/Wait如何帮助用户界面响应吗
- async/await与以前的异步功能(如setTimeout和XmlHttpRequest)有何关联
异步
是构造异步代码的一种更优雅的方式。它不允许任何新功能;它只是一种比回调或承诺更好的语法
因此,
async
不能用于“使某些东西异步”。如果您的代码需要执行大量基于CPU的处理,async
不会神奇地使UI响应。您需要做的是使用类似的工具,这是将CPU绑定的工作推送到后台线程的合适工具,以便使UI响应。wait p
在promisep
解决时安排其余函数的执行。就这些
async
允许您使用wait
。这(几乎)就是它所做的一切(它还将你的结果包装成一个承诺)
它们一起使非阻塞代码读起来像更简单的阻塞代码。他们不会解锁代码
对于响应性UI,将CPU密集型工作卸载到线程,并向其传递消息:
异步函数bruteprome(n){
函数功({data}){
while(true){
设d=2;
对于(;dworker.onmessage=e=>resolve(e.data));
}
(异步()=>{
设n=70000000;
for(设i=0;i<10;i++){
log(n=await bruteprome(n+1));
}
})().catch(e=>console.log(e))代码>JavaScript是单线程的,与UI在同一线程中运行。因此,所有JavaScript代码都会阻塞UI。正如其他人所提到的,web工作者可以用来在其他线程中运行代码,但它们有局限性 异步函数和常规函数的区别在于它们返回一个承诺。然后,使用回调可以推迟代码的执行,这将处理函数调用的结果,从而允许UI执行一些工作。以下三个示例具有相同的效果:
async function foo() {
console.log("hi");
return 1;
}
foo().then(result => console.log(result))
console.log("lo");
function foo() {
console.log("hi");
return 1;
}
Promise.resolve(foo()).then(result => console.log(result))
console.log("lo");
function foo() {
console.log("hi");
return 1;
}
const result = foo();
setTimeout(() => console.log(result));
console.log("lo");
在这三种情况下,控制台都会记录hi、lo和1。在打印1之前,UI可以处理用户输入或绘图更新。在前两种情况下最后打印的原因1是承诺的回调不会立即执行
wait
允许您无需回调即可完成此操作:
async function foo() {
console.log("hi");
return 1;
}
async function bar() {
const result = await foo();
console.log(result);
}
bar();
console.log("lo");
这也将打印hi,lo,1。与承诺的回调非常相似,
wait
之后的代码永远不会立即执行。从描述中可以清楚地看出,它是非阻塞的:
wait关键字导致JavaScript运行时暂停代码 这一行,允许同时执行其他代码(注意:我的粗体),直到 异步函数调用已返回其结果。完成后, 代码从下一行开始继续执行
阻止的代码仍将阻止。如果没有,你可能会有数据竞赛。异步函数的思想是,您可以原地停止,等待异步代码稍后执行。因此,您在等待异步操作完成时会暂停,例如
setTimeout
、XHR响应或事件单击事件:(演示需要支持的浏览器)async/await
不是ES7(ES2016)的一部分。这将是今年发布的ES2017的一部分。为没有外部文件的员工提供积分。这是一个很酷的技巧。异步函数也会返回一个promise。我想您可以这样使用它来停止循环阻塞。对于(设i=0;i<100000;i++){wait delay(10)}异步函数delay(ms){return new Promise((resolve,reject))=>setTimeout(resolve,ms));}@Martian2049:Yesasync
是建立在承诺之上的,承诺是非阻塞的。“它不允许任何新功能”,实际上是这样的。“因此,异步不能用于“使某些东西异步”,但wait
可以。@abetteroliver:也许我们在看不同的语义。当我说“[async]不允许任何新功能时。”",我的意思是,使用async
所能做的一切都可以不用async
使用回调/承诺来完成,这是可以证明的,因为直到最近async
还是一个编译时代码转换,没有运行时支持。async
已经有相当长的一段时间了,您需要的转换指的是发电机的使用。生成器函数和异步函数都保留堆栈,基本上允许暂停函数。你不能用承诺来实现这一点。当然,您是对的,await
并不会使API异步,但由于(本机)的异步性质,其他代码可能(!)在函数继续之前得到执行的机会。如果您等待bar()呢?@Rodrigo您只能在异步函数内部等待。为什么hi
在lo
之前打印?@zzzzzbar
在console.log(“lo”)
之前被调用,它调用foo
,后者调用console.log(“hi”)
@zzzzzzz异步函数返回一个承诺<代码>等待等待承诺得到解决或拒绝,而这一切都是如此