Javascript异步函数的“等待"的正确思维模型:生成器的“产量"与"promise.then()"? [英] Correct mental model for a Javascript async function's 'await': generator's 'yield' vs. 'promise.then()'?

查看:98
本文介绍了Javascript异步函数的“等待"的正确思维模型:生成器的“产量"与"promise.then()"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

发电者的收益与诺言之间的哪个.then()是更*正确的心理模型,用于理解等待"?

Which of a generator's yield vs. promise.then() is a more* correct mental model for understanding 'await'?

属性比较,通过使用调试器逐步浏览以下代码段来推断:

Property comparison, inferred by stepping through the snippet below with a debugger:

等待:

  1. await不会暂停/暂停正在运行的异步功能的执行.(正在运行的异步功能运行至完成",当解释器达到第一个等待状态时,将返回一个未完成的诺言.然后立即将其从调用堆栈中删除.)

  1. await does not pause/suspend the running async function’s execution. (The running async function ‘runs to completion’, returning a pending promise when the interpreter hits the 1st await. It’s then immediately removed from the call stack.)

await等待诺言兑现.

await waits for the promise to settle.

await表达式将函数的其余代码包装在微任务中.

await expression wraps the rest of a function's code in a microtask.

发电量:

  1. yield暂停正在运行的功能的执行.生成器功能不会运行完成".
  2. 收益承诺确实确保在执行剩余代码之前已经解决了 promise .
  3. yield不包装或创建微任务.
  1. yield pauses the running function’s execution. generator functions do not ‘run to completion’.
  2. yield promise does ensure promise has settled prior to executing remaining code.
  3. yield does not wrap or create a microtask.

promise.then(回调):

promise.then(callback):

  1. 不暂停正在运行的功能的执行.
  2. 等待承诺完成,然后执行回调.
  3. 创建一个微任务(回调)

//promise returning function
function foo(whoCalled) {
   let p = new Promise(function(resolve, reject) { 
     setTimeout( () => {
       console.log('resolving from setTimeout - called by: ' + whoCalled)
       resolve('resolve value') }, .1)
   })
   return p
}

//async await
async function asyncFunc() {
  await foo('async function')
  //rest of running function’s code…
  console.log('async function howdy')
}

//generator yield:
function* gen() {
   yield foo('generator function')
   //rest of running function’s code…
   console.log('generator function howdy')
}

//promise.then():
function thenFunc() {
   let r = foo('promise.then function').then(() => {
       //rest of running function’s code…
       console.log('promise.then() howdy')
   })
   return r
}

//main
function main() {

  //async await
  var a = asyncFunc() 
  console.log(a) //logs Promise { <pending> }
                 //the rest of the code following await foo() runs as a microtask runs once foo() resolves. The call stack was cleared.

  //generator
   var g = gen()
   console.log(g) // logs Object [Generator] {}
   var p = g.next().value
   console.log(p) //logs Promise { <pending> }
   g.next()       //the rest of the code following yield running gen function's code runs. call stack was not cleared.

   //promise.then()
   var x = thenFunc()
   console.log(x) //logs Promise { <pending> }
                   //the then(callback) microtask runs once foo() resolves. The call stack was cleared
}
main()
console.log('main is off the call stack - launch/startup macrotask completing. Event loop entering timer phase.')

而且,除了这种比较之外, await 在幕后所做的准确的心理模型是什么?

And, going beyond this comparison, what is the accurate mental model of what await does under the hood?

等待最新的ECMAScript规范以供参考: https://www.ecma-international.org/ecma-262/10.0/index.html#await

await in latest ECMAScript spec for reference: https://www.ecma-international.org/ecma-262/10.0/index.html#await

在V8源代码中等待:

await in V8 source code: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/builtins/builtins-async-function-gen.cc#L252

推荐答案

这不是一个.实际上,两者都在一起: async / await = yield + then +一个跑步者.

It's not one or the other. Actually it's both of them together: async/await = yield + then + a runner.

async函数确实被 await 关键字挂起,就像生成器 function * 确实被 yield 关键字.在控制流语句中间停止执行和恢复执行的机制是完全相同的.

An async function does get suspended by the await keyword just like a generator function* does get suspended by the yield keyword. The mechanism of how the execution gets stopped and resumed in the middle of control flow statements is exactly the same.

不同之处在于这些连续的驱动方式以及函数返回的内容.生成器函数在被调用时会创建一个生成器对象,您必须从外部显式调用 next()方法以按 yield yield >.另一方面,异步函数会创建一个Promise,并自行管理执行.它不等待外部 next()调用,而是尽快运行每个异步步骤.与其从那些 next()调用中返回所产生的值,它不对等待的值进行 Promise.resolve()到一个Promise,然后调用其 then 方法将继续作为回调传递.到达 return 时,它不会向调用方发出迭代结束"的信号,而是使用返回值来解析最初返回的promise.

What differs is how these continuations are driven, and what the functions return. A generator function creates a generator object when called, and you have to explicitly invoke the next() method from outside to run the code yield by yield. An async function on the other hand creates a promise, and manages the execution by itself. It doesn't wait for external next() calls but runs each asynchronous step as soon as possible. Instead of returning the yielded values from those next() calls, it does Promise.resolve() the awaited values to a promise, and calls its then method passing the continuation as the callbacks. Instead of signalling an "end of iteration" to the caller when reaching a return, it resolves the originally returned promise with the return value.

这篇关于Javascript异步函数的“等待"的正确思维模型:生成器的“产量"与"promise.then()"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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