在Javascript中没有等待的异步功能

Uly*_* BN 32 javascript asynchronous async-await

我有两个函数a,b它们是异步的,前者没有await,后者则是await.他们都记录了一些东西到控制台并返回undefined.在调用任一函数后,我记录另一条消息,并查看是否在执行函数体之前或之后写入消息.

function someMath() {
  for (let i = 0; i < 3000000; i++) { Math.sqrt(i**5) }
}

function timeout(n) {
   return new Promise(cb => setTimeout(cb, n))
}

// ------------------------------------------------- a (no await)
async function a() {
  someMath()
  console.log('in a (no await)')
}

// ---------------------------------------------------- b (await)
async function b() {
  await timeout(100)
  console.log('in b (await)')
}

clear.onclick = console.clear

aButton.onclick = function() {
  a()
  console.log('after a (no await) call')
}

bButton.onclick = function() {
  b()
  console.log('after b (await) call')
}
Run Code Online (Sandbox Code Playgroud)
<button id="aButton">test without await</button>
<button id="bButton">test with await</button>
<button id="clear">clear console</button>
Run Code Online (Sandbox Code Playgroud)

如果你启动测试没有await该功能似乎工作,就好像它是同步的.但是await,当函数异步执行时,消息被反转.

所以我的问题是:当没有关键字存在javascript如何执行async函数await


真实用例:我有一个await条件执行的关键字,我需要知道函数是否同步执行才能呈现我的元素:

async function initializeComponent(stuff) {
   if (stuff === undefined)
      stuff = await getStuff()
   // initialize

   if (/* context has been blocked */)
       renderComponent() // render again if stuff had to be loaded
}

initializeComponent()
renderComponent()
Run Code Online (Sandbox Code Playgroud)

PS:title有javascript关键字,以避免与其他语言中的相同问题混淆(即使用async而不等待)

Kar*_*rim 28

来自mozilla doc:

异步函数可以包含await表达式,它暂停执行异步函数并等待传递的Promise的解析,然后恢复异步函数的执行并返回已解析的值.

正如您所建议的那样,如果没有等待,则执行不会暂停,您的代码将同步执行.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#Description

  • 在返回promise但不使用`await`的函数中声明'async'的一个好处是异常将被拒绝而不是同步抛出.例如`const result = someAsyncFunctionWithoutAwait().catch(handleRejection)` (7认同)
  • 冗余`async`关键字是否有eslint规则?我不认为同步功能应该有它 (2认同)
  • 换句话说,这个答案不应该说“如果不存在等待,则执行不会暂停,但您的代码仍将以非阻塞方式执行”而不是“如果不存在等待,则执行不会暂停并且然后您的代码将同步执行”?此外,如果不存在 async 和 await,您的代码仍将是非阻塞的(例如,使用 async 关键字声明函数而不使用 await 等效于不使用 async 关键字声明相同的函数)。 (2认同)
  • 一个很好的看待方式是 Async/Await 允许您*同步*异步代码: `async function dummy(){ /*...*/ return Promise.resolve(/*...*/); } 异步 dummyAsync(){ dummy(); nextDummy(); } async dummySync(){ 等待 dummy(); nextDummy(); }`。在 **dummyAsync** 中,在 `dummy()` 完成之前,没有任何东西可以阻止 `nextDummy()` 执行;它的*异步*。在 ***dummySync*** 中,直到 `dummy()` 的 Promise 解析(返回)后,`nextDummy()` 才会执行;它是“同步”或“按程序编写的”异步代码。@AdrianPop 提供了声明 async 且不调用 wait 的完美用途。 (2认同)

Bar*_*mar 12

该功能在有或没有的情况下执行相同await.什么await是自动等待要解析的函数返回的承诺.

await timeout(1000);
more code here;
Run Code Online (Sandbox Code Playgroud)

大致相当于:

timeout(1000).then(function() {
    more code here;
});
Run Code Online (Sandbox Code Playgroud)

async function声明只是使功能自动返回时,函数返回的问题得以解决的承诺.


NAV*_*VIN 12

在执行Javascript异步功能之前,所有操作都是同步的。在使用async-await时await是异步的,将await之后的所有内容放入事件队列中。类似于.then()

为了更好地解释,请看以下示例:

function main() {
  return new Promise( resolve => {
    console.log(3);
    resolve(4);
    console.log(5);
  });
}

async function f(){
    console.log(2);
    let r = await main();
    console.log(r);
}

console.log(1);
f();
console.log(6);
Run Code Online (Sandbox Code Playgroud)

由于await异步和其余所有都是同步的,包括承诺,因此输出为

1
2
3
5
6
// Async happened, await for main()
4
Run Code Online (Sandbox Code Playgroud)

的类似行为main()也是没有前途的:

function main() {
    console.log(3);
    return 4;
}

async function f(){
    console.log(2);
    let r = await main();
    console.log(r);
}

console.log(1);
f();
console.log(5);
Run Code Online (Sandbox Code Playgroud)

输出:

1
2
3
5
// Asynchronous happened, await for main()
4
Run Code Online (Sandbox Code Playgroud)

只需删除即可await使整个async功能保持同步。

function main() {
    console.log(3);
    return 4;
}

async function f(){
    console.log(2);
    let r = main();
    console.log(r);
}

console.log(1);
f();
console.log(5);
Run Code Online (Sandbox Code Playgroud)

输出:

1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)

  • **请注意,这是 ES11 之前的旧实现。在 ES11 中,事情发生了一些变化。但这仍然有效。** (3认同)
  • 您还可以添加一个执行 var g = wait f() 的函数,因为 f() 是异步的,如果您不想阻止主执行线程,则可能需要在长时间运行的进程中等待。 (2认同)
  • 事件队列中的代码(**await**之后的所有内容)是否总是在主线程完成后运行?我的意思是,在您的两个示例中,在最后一个“console.log”之后,事件队列运行,并且“等待”的代码最终执行。如果我们有更多的指令和更多的代码,在最后一条指令之后,等待的代码是否仍然会运行? (2认同)

tev*_*dar 7

正如其他答案所说/表明的那样: anasync function只是在现场运行,直到遇到一个await- 如果没有await,则它会完全运行。

可能值得添加的是async无条件地使您的结果成为Promise. 所以如果你返回一些东西,已经有区别了,如果不首先返回到 JS 引擎,你根本无法得到结果(类似于事件处理):

async function four(){
  console.log("  I am four");
  return 4;
}
console.log(1);
let result=four();
console.log(2,"It is not four:",result,"Is it a promise ?", result instanceof Promise);
result.then(function(x){console.log(x,"(from then)");});
console.log(3);
Run Code Online (Sandbox Code Playgroud)