4.Promise

1.什么是promise

Promise是异步编程的一种解决方案:从语法上来讲,promise是一个对象,从他可以获取异步操作的消息;从本意上来讲。他是一个承诺,承诺他过一段时间会给你一个结果。

他有三种状态:pending(等待态)、fulfiled(成功态)、rejected(失败态);状态一旦改变,就不会再变。

promise是用来解决两个问题的:

  • 回调地狱
  • 支持多个并发
  • promise可以解决异步的问题,本身不能说promise是异步的

2.如何实现Promise及Promise.resolve等方法

说到底,Promise还是使用回调函数,只不过是把回调封装在了内部,使用上一直通过then方法的链式调用,使得多层的回调嵌套看起来变成了同一层的。

//极简的实现
class Promise {
    callbacks = [];
    constructor(fn) {
        fn(this._resolve.bind(this));
    }
    then(onFulfilled) {
        this.callbacks.push(onFulfilled);
    }
    _resolve(value) {
        this.callbacks.forEach(fn => fn(value));
    }
}

//Promise应用
let p = new Promise(resolve => {
    setTimeout(() => {
        console.log('done');
        resolve('5秒');
    }, 5000);
}).then((tip) => {
    console.log(tip);
})

3.async/await如何实现的

首先Promise能很好地解决回调地狱的问题,但是这种方法充满了Promise的then方法,

如果处理复杂的的话,语义化不明显,执行流程不能很好表示。

于是ES7引入了async/await,

提供了在不阻塞主线程的情况下使用同步代码实现异步访问资源的能力,并且使得代码逻辑更加清晰

上来就讲怎么实现肯定听不懂,所以我们一步一步讲。

生成器如何工作

生成器函数是一个带星号函数,而且是可以暂停执行和恢复执行的

具体使用方式:

  1. 在生成器函数内部执行一段代码,如果遇到 yield 关键字,那么 JavaScript 引擎将返回关键字后面的内容给外部,并暂停该函数的执行。
  2. 外部函数可以通过 next 方法恢复函数的执行

函数为什么能停止和恢复呢?

了解一下协程,协程是一种比线程更加轻量级的存在,你可以把协程看成是跑在线程上的任务

  1. 通过调用生成器函数 genDemo 来创建一个协程 gen,创建之后,gen 协程并没有立即执行。
  2. 要让 gen 协程执行,需要通过调用 gen.next。
  3. 当协程正在执行的时候,可以通过 yield 关键字来暂停 gen 协程的执行,并返回主要信息给父协程。
  4. 如果协程在执行期间,遇到了 return 关键字,那么 JavaScript 引擎会结束当前协程,并将 return 后面的内容返回给父协程。

其实在 JavaScript 中,生成器就是协程的一种实现方式,利用下面的步骤

  • 首先执行的是let gen = foo(),创建了 gen 协程。然后在父协程中通过执行 gen.next 把主线程的控制权交给 gen 协程。
  • gen 协程获取到主线程的控制权后,就调用 fetch 函数创建了一个 Promise 对象 response1,然后通过 yield 暂停 gen 协程的执行,并将 response1 返回给父协程。
  • 父协程恢复执行后,调用 response1.then 方法等待请求结果。
  • 等通过 fetch 发起的请求完成之后,会调用 then 中的回调函数,then 中的回调函数拿到结果之后,通过调用 gen.next 放弃主线程的控制权,将控制权交 gen 协程继续执行下个请求。

把执行生成器的代码封装成一个函数,并把这个函数称为执行器。

虽然生成器已经满足我需求了,但是不够简洁,

其实 async/await 技术背后的秘密就是 Promise 和生成器应用,往低层说就是微任务和协程应用。

async

根据 MDN 定义,async 是一个通过异步执行隐式返回 Promise 作为结果的函数。

await

async function foo() {
    console.log(1)
    let a = await 100
    console.log(a)
    console.log(2)
}
console.log(0)
foo()
console.log(3)

执行到await 100时,会默认创建一个 Promise 对象,代码如下所示

let promise_ = new Promise((resolve,reject){
  resolve(100)
})

在这个 promise_ 对象创建的过程中,我们可以看到在 executor 函数中调用了 resolve 函数,JavaScript 引擎会将该任务提交给微任务队列。

因为 async/await 的基础技术使用了生成器和 Promise,生成器是协程的实现,利用生成器能实现生成器函数的暂停和恢复。

另外,V8 引擎还为 async/await 做了大量的语法层面包装

 

posted @ 2023-03-04 20:04  不想做混子的奋斗远  阅读(11)  评论(0)    收藏  举报