async and await in JavaScript

异步事件,同步等待的需要让 JavaScript 引入了 asyncawait 语法。

await in JavaScript

The await operator is used to wait for a Promise.

It can only be used inside an async function.

根据 Mozilla async function 文档的例子改动的示例。

function fetchNumber() {
  return new Promise(function(resolve){
    setTimeout(function(){
      let number = Math.ceil(Math.random()*10);
      resolve(number);
    }, 2000);
  });
}

async function fetchAdd(x) {
      console.log("await 0");
  const a = await fetchNumber();
      console.log("await 1");      // print after 2 seconds
  const b = await fetchNumber();
      console.log("await 2");      // print after 4 seconds
  return x + a + b;
}

function delayPrint(ms, message){
  setTimeout(function(){
     console.log(message);
  }, ms)
}

delayPrint(1000, "after 1 seconds");  // expect after 1 seconds
delayPrint(3000, "after 3 seconds");  // expect after 3 seconds


fetchAdd(10).then(function(result){
  console.log("result =", result);  // print after 4 seconds.
});

console.log("pone")

执行结果输出的顺序是

await 0
pone                  // 表明 async 函数是 "立即" 返回
after 1 seconds       // 表明 await 没有阻塞整个程序的运行
await 1               // 表明 await 阻塞了函数内代码的运行
after 3 seconds
await 2

可见 await 起到了暂停函数执行的效果。

await ~= yield

可以让函数执行暂停,稍后继续的是协程 coroutine,它通过 yield 语句暂停函数执行,稍后可以从暂停的地方继续执行。

async 返回 Promise

同时,上面的例子也表明,用 async 标记的函数隐式地返回一个 Promise.

async function fetchAdd(x) {
    let y = await fetchNumber();
    return x + y;
}

fetchAdd(10).then(function(result){
    console.log("result =", result);
});

vwait in Tcl

在 Tcl 语言里类似 await 的代码是


after 2000 {
  set number 123
  set ::ready 1
}

vwait reader               ;# 等待异步事件结束

puts "number = $number"