JavaScript Promises, async/await

这篇博客不是讲如何使用 Promise,是一个学习总结。是我自己对 Promise 的理解。

new Promise() 的时候,传一个 executor 给 Promise.

let promise = new Promise(function(resolve, reject) {
  // this function will executes immediately
})

这个函数会立刻被执行,在 executor 里面调用了 resolve 之后, Promise 变为 fulfilled,在 executor 里面调用了 reject 之后,Promise 变为 rejected。如果 resolve 和 reject 都还没被调用,Promise 的状态是 pending(等待结果)。.then/.catch/.finally都是异步的,JavaScript 是单线程模型,所有的异步任务都将被放到任务队列里,等主线程的所有的代码执行完然后才执行任务队列里的任务。JavaScript 是单线程,也就是所有的异步代码都会等到 JS 文件里面的代码都执行完了才执行。也就是说,即便 Promise 立刻 settle,.then/.catch/.finally 的代码也不会立刻执行,要等到主线程空闲的时候才执行,

《JavaScript Promises, async/await》

setTimeout() 是异步的,不会阻塞函数执行,所以 let promise 立刻得到了 Promise 对象。Promise 的 state 和 result 都是内部的,不能直接访问。要拿到 result, 就要使用 .then 或者 .catch 方法,传一个接受结果的函数给他们。Promise.resolve() 就相当于 new Promise(resolve => resolve())Promise.reject() 相当于是 new Promise((resolve, reject) => reject())

《JavaScript Promises, async/await》

.then.catch 都是返回一个 Promise 对象,而 Promise 对象有 then 和 catch 方法,所以可以链起来。这个 undefined 是 console.log(r) 的输出。

《JavaScript Promises, async/await》

在 then 里面也可以 return new Promise(…)1。对于错误处理,executor 外部有一个隐式的 try…catch,也就是说 executor 执行流的异常会被后来最近的 .catch() 调用捕获到,没有捕获的的错误最后会被抛到 window,或者全局。值得注意的是 .catch() 处理异常以后也会返回一个 Promise 对象。

async 意味着函数一定返回一个 Promise,如果函数正常 return,return 的结果在一个 resolved Promise 里面。.then() 里面可以返回一个 Promise,在 async 函数里面也可以显式的返回一个 Promise。

await 不是单纯的等待,不是阻塞的等待,literally suspends the function execution,实际上是挂起这个函数的执行,或者说暂停这个函数的执行,等 Promise settle 也是就是等 Promise 有结果之后,然后 resume(恢复)执行。这就有点像是生成器的 yield,从上次打断的地方恢复执行。await 挂起/暂停的时候CPU执行其他的异步任务,await 有等待的意思,不过实际上还有让步,会将执行权让给其他的任务,等其他的任务执行完或者其他的任务让步以后,然后继续之前 await 的时候让步离开的地方执行。具体会运行到哪个异步任务,得看当时任务队列里面有什么任务在等待执行。

Let’s emphasize: await literally suspends the function execution until the promise settles, and then resumes it with the promise result. That doesn’t cost any CPU resources, because the JavaScript engine can do other jobs in the meantime: execute other scripts, handle events, etc.

await 会去调用.then(),获取 Promise 的结果。async/await 使得调用异步函数,不需要写回调了,也不需要一直 .then,异步代码就像普通的代码一样。

async/await 是一个比较通用的关于协程的关键字。这其实就是 JavaScript 的协程,可以实现单线程的并发。协程简单来说就是一个会记住状态的函数,就像生成器一样,重新进入函数的时候会从上次离开的地方继续。

Funny Promise, async/await

下面是一个好玩的例子,用 Promise 重写使用 await 的斐波那契数列。

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function async_fib(n) {
  if (n == 0)
    return 0
  else if (n == 1)
    return 1
  
  await sleep(1000)

  return await async_fib(n - 1) + await async_fib(n - 2)
}

function fib(n) {
  if (n == 0) {
    return 0
  } else if (n == 1) {
    return 1
  }
  
  return sleep(1000)
          .then(() => {
            const f = fib(n-1);
            if (f.then)
              return f.then(left => {
                  const g = fib(n-2)
                  if (g.then)
                    return g.then(right => {
                      return left + right
                    })
                  else
                    return left + g
                });
            else
              return f
          })
}

fib(3).then(res => console.log(res))

    原文作者:fnmain
    原文地址: https://www.cnblogs.com/fnmain/p/16961646.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞