鸿蒙应用开发-Promise演进及在鸿蒙中的源码实现

496 阅读32分钟

Generator 生成器函数

Generator 是一个生成遍历器对象的函数 同时它也是一个状态机。通过它返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态

语法

// function关键字和函数名之间有一个星号
function* helloWorldGenerator() {
  // 函数体内部通过yield表达式定义不同的内部状态
  yield 'hello';
  yield 'world';
  return 'ending';
}

const hw = helloWorldGenerator();

使用

和普通函数调用一样。不同的是,Generator的返回值是一个迭代器

  1. 调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。
  2. 以后,每次调用遍历器对象的next方法,就会返回一个有着valuedone两个属性的对象。
  3. value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束
hw.next()
// Generator 函数开始执行,直到遇到第一个yield表达式为止
// { value: 'hello', done: false }

hw.next()
// Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式
// { value: 'world', done: false }

hw.next()
// Generator 函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束)
// { value: 'ending', done: true }

hw.next()
// Generator 函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true。以后再调用next方法,返回的都是这个值
// { value: undefined, done: true }

生成器的另一种用法是:内部不使用yield表达式,仅作为一个惰性执行函数

function* f() {
  console.log('执行了!')
}
// 这里只是调用f获得了一个迭代器,此时console.log不会执行
const generator = f();
// 只有调用next,console.log才会执行
generator.next()

迭代器 Iterator与yield表达式

迭代器可以理解成一个有next方法的对象,通过迭代器不断的调用next方法进行遍历状态。在JS中迭代器借助yield实现,yield表达式可以暂停函数的执行。

遍历器对象的next方法的运行逻辑

(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。

(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

(4)如果该函数没有return语句,则返回的对象的value属性值为undefined

需要注意的是,yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行

对象的Symbol.iterator

任意一个对象的 Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象

Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性

const myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

[...myIterable] // [1, 2, 3]

迭代器的Symbol.iterator

Generator 函数执行后,返回一个遍历器对象。该对象本身也具有Symbol.iterator属性,执行后返回自身

function* gen(){
  // some code
}

const g = gen();

g[Symbol.iterator]() === g
// true

迭代器的next()、throw()、return() 

迭代器对象除了next方法,还有throw,return方法,它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式

next

next()是将yield表达式替换成一个值

const g = function* (x, y) {
  let result = yield x + y;
  return result;
};

const gen = g(1, 2);
gen.next(); // Object {value: 3, done: false}

gen.next(1); // Object {value: 1, done: true}
// 相当于将 let result = yield x + y
// 替换成 let result = 1;

throw

throw()是将yield表达式替换成一个throw语句

gen.throw(new Error('出错了')); // Uncaught Error: 出错了
// 相当于将 let result = yield x + y
// 替换成 let result = throw(new Error('出错了'));

return

return()是将yield表达式替换成一个return语句

gen.return(2); // Object {value: 2, done: true}
// 相当于将 let result = yield x + y
// 替换成 let result = return 2;

yield* 表达式

用来在一个 Generator 函数里面执行另一个 Generator 函数。这个Generator函数即可以是同步的也可以是异步的

function* foo() {
  yield 'a';
  yield 'b';
}

function* bar() {
  yield 'x';
  yield* foo();
  yield 'y';
}

// 等同于
function* bar() {
  yield 'x';
  yield 'a';
  yield 'b';
  yield 'y';
}

// 等同于
function* bar() {
  yield 'x';
  for (let v of foo()) {
    yield v;
  }
  yield 'y';
}

for (let v of bar()){
  console.log(v);
}
// "x"
// "a"
// "b"
// "y"

异步遍历器

异步遍历器的最大的语法特点,就是调用遍历器的next方法,返回的是一个 Promise 对象

一个对象的同步遍历器的接口,部署在**Symbol.iterator属性上面。同样地,对象的异步遍历器接口,部署在Symbol.asyncIterator**属性上面

语法

异步遍历器其实返回了两次值。第一次调用的时候,返回一个 Promise 对象;等到 Promise 对象resolve了,再返回一个表示当前数据成员信息的对象。

这就是说,异步遍历器与同步遍历器最终行为是一致的,只是会先返回 Promise 对象,作为中介

const asyncIterable = createAsyncIterable(['a', 'b']);
const asyncIterator = asyncIterable[Symbol.asyncIterator]();

asyncIterator
.next()
.then(iterResult1 => {
  console.log(iterResult1); // { value: 'a', done: false }
  return asyncIterator.next();
})
.then(iterResult2 => {
  console.log(iterResult2); // { value: 'b', done: false }
  return asyncIterator.next();
})
.then(iterResult3 => {
  console.log(iterResult3); // { value: undefined, done: true }
});

使用for await of遍历异步迭代器

for...of循环用于遍历同步的 Iterator 接口。for await...of循环,则是用于遍历异步的 Iterator 接口

async function f() {
  // createAsyncIterable()返回一个拥有异步遍历器接口的对象
  // for...of循环自动调用这个对象的异步遍历器的next方法,会得到一个 Promise 对象
  // await用来处理这个 Promise 对象,一旦resolve,就把得到的值(x)传入for...of的循环体
  for await (const x of createAsyncIterable(['a', 'b'])) {
    console.log(x);
  }
}
// a
// b

异步Generator

异步 Generator 函数的作用,是返回一个异步遍历器对象

async function* gen() {
  yield 'hello';
}
// gen是一个异步 Generator 函数,执行后返回一个异步 Iterator 对象
const genObj = gen();
// 对该对象调用next方法,返回一个 Promise 对象
genObj.next().then(x => console.log(x));
// { value: 'hello', done: false }

dart中的迭代器一撇

dart中也有生成器一说,语法和JS很类似,我们就简单看一下就行

// 同步生成器的返回值是Iterable,函数体要使用sync*修饰
Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  // 生成器分为同步生成器和异步生成器,函数内部使用yield生成值
  while (k < n) yield k++;
}

// 生成器使用时必须调用next()方法
var gen = naturalsTo(3)
gen.next()

// 异步生成器的返回值是Stream,函数体要使用async*修饰
Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

// 递归语法的生成器
// 如果生成器是递归语法写的,使用yield* 可以提高效率
Iterable<int> naturalsDownFrom(int n) sync* {
  if (n > 0) {
    yield n;
    yield* naturalsDownFrom(n - 1);
  }
}

Promise

Promise是一个对象,用于封装一个将来发生的操作(或者叫异步操作),这个操作要么完成时返回结果值或者要么失败时返回失败原因

Promise的状态

可以把Promise理解成是一个状态机,它内部有三个状态

pending:初始态

fulfilled:成功时的状态

rejected:失败时的状态

Promise的特性

  1. Promise只会由pending转换到另外两个状态之一,不会逆向转换。并且转换只会发生一次。
  2. Promise的状态只能由Promise内部修改,外部无法修改
  3. 无法取消Promise,创建一个Promise时,参数内的代码会立即执行
  4. 一旦Promise转换成fulfilled或rejected状态,这个promise就叫做被settled。被settled之后的promise,如果调用then或finally方法,这些方法传入的回调函数会立即放入微任务队列等待执行
  5. 同一个Promise多次调用then、finally方法,内部会将对应的回调存储到一个数组中。待状态变化时遍历数组调用回调函数
  6. 可以将catch方法看成是then(null, rejection)或者then(undefined,rejection)的别名,相当于一个只指定了第二个参数的then方法
  7. 如果没有使用catch指定错误处理的回调函数,Promise对象抛出错误的时候就不会传递到外层代码。即不会有任何反应。其原因在于,在Promise使用try catch捕获了错误,然后传递到了reject回调里,没有抛出到外面

下图展示了Promise状态转换的示意

image.png

链式调用

Promise的then、catch、finally都会返回一个新的Promise,新的Promise还可以继续调用then、catch、finally再返回新的Promise,从而通过一个个新的Promise完成链式调用

async、await

async/await实际上是对Generator(生成器)的封装,是一个语法糖

async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果

async

async表示一个函数是异步的,会返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句

async函数有多种形式

// 函数声明
async function foo() {}

// 函数表达式
const foo = async function () {};

// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)

// Class 的方法
class Storage {
  constructor() {
    this.cachePromise = caches.open('avatars');
  }

  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}

const storage = new Storage();
storage.getAvatar('jake').then(…);

// 箭头函数
const foo = async () => {};

细节

async函数返回一个 Promise 对象。async函数内部return语句返回的值,会成为then方法回调函数的参数

如果在函数中return的不是一个promise,那么将等同于使用Promise.resolve(x)给包装起来。这其中也包括不写return时返回的undefined

async function f() {
  return 'hello world';
}

f().then(v => console.log(v))
// "hello world"

async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到

async function f() {
  throw new Error('出错了');
}

f().then(
  v => console.log('resolve', v),
  e => console.log('reject', e)
)
//reject Error: 出错了

只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数

async function getTitle(url) {
  // 等待fetch方法产生的promise完成,才会执行response.next
  let response = await fetch(url);
  // 等待response.next方法执行完成,才会执行html.match
  let html = await response.text();
  return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"

实现原理

async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里

async function fn(args) {
  // ...
}

// 等同于
function fn(args) {
  return spawn(function* () {
       yield step1
	   yield step2
       yield step3
       . . . 
  });
}

await

await命令后面如果是一个 Promise 对象,会返回该对象的结果。如果不是 Promise 对象,会直接返回对应的值

只能在async函数内部使用

任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行

async function f() {
  await Promise.reject('出错了');
  await Promise.resolve('hello world'); // 不会执行
}

在鸿蒙中的实现

await promise最终会被转化成一个函数  gitee.com/openharmony… 

EtsObject *EtsAwaitPromise(EtsPromise *promise)

从代码中我们也能够知道,在鸿蒙底层await是通过协程实现的

await会一直等待它后面promise的状态变成resolved或者rejected。如果它后面的promise一直不变状态,await下面的代码就一直不会执行,这点需要特别注意

image.png

鸿蒙中Promise的实现

Promise A+规范

英文原版 promisesaplus.com/

中文翻译 www.ituring.com.cn/article/665…

Promise/A+ 规范中定义的 Promise 的基本特征:

  1. promise 有三个状态:pendingfulfilled,or rejected;「规范 Promise/A+ 2.1」
  2. new promise, 需要传递一个executor()执行器,执行器立即执行
  3. executor接受两个参数,分别是resolvereject
  4. promise 的 默认状态是 pending
  5. promise 有一个**value保存成功状态的值**,可以是undefined/thenable/promise;「规范 Promise/A+ 1.3」
  6. promise 有一个**reason保存失败状态的值**;「规范 Promise/A+ 1.5」
  7. promise 只能从pendingrejected, 或者从pendingfulfilled,状态一旦确认,就不会再改变
  8. promise 必须有一个then方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 和 promise 失败的回调 onRejected;「规范 Promise/A+ 2.2」
  9. 如果调用 then 时,promise 已经成功,则执行onFulfilled,参数是promisevalue
  10. 如果调用 then 时,promise 已经失败,那么执行onRejected, 参数是promisereason
  11. 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个 then 的失败的回调onRejected
  12. then 的参数 onFulfilled 和 onRejected 可以缺省,如果 onFulfilled 或者 onRejected不是函数,将其忽略,且依旧可以在下面的 then 中获取到之前返回的值;「规范 Promise/A+ 2.2.1、2.2.1.1、2.2.1.2」
  13. promise 可以 then 多次,每次执行完 promise.then 方法后返回的都是一个“新的promise" ;「规范 Promise/A+ 2.2.7」
  14. 如果 then 的返回值 x 是一个普通值,那么就会把这个结果作为参数,传递给下一个 then 的成功的回调中;
  15. 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个 then 的失败的回调中;「规范 Promise/A+ 2.2.7.2」
  16. 如果 then 的返回值 x 是一个 promise,那么会等这个 promise 执行完,promise 如果成功,就走下一个 then 的成功;如果失败,就走下一个 then 的失败;如果抛出异常,就走下一个 then 的失败;「规范 Promise/A+ 2.2.7.3、2.2.7.4」
  17. 如果 then 的返回值 x 和 promise 是同一个引用对象,造成循环引用,则抛出异常,把异常传递给下一个 then 的失败的回调中;「规范 Promise/A+ 2.3.1」
  18. 如果 then 的返回值 x 是一个 promise,且 x 同时调用 resolve 函数和 reject 函数,则第一次调用优先,其他所有调用被忽略;「规范 Promise/A+ 2.3.3.3.3」

源码

翻了一下资料,最终在 gitee.com/openharmony… 中发现了鸿蒙中Promise的封装。

/*
 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package std.core;
// 定义Promise的接口类型
export interface PromiseLike<T> {
    then<U>(onFulfilled: () => U|PromiseLike<U> throws): PromiseLike<U>;
    then<U>(onFulfilled: (value: T) => U|PromiseLike<U> throws): PromiseLike<U>;
    // NOTE(audovichenko): Mark parameters by '?' instead of add '|undefined'. Issue #17204
    then<U, E = never>(onFulfilled: ((value: T) => U|PromiseLike<U> throws)|undefined,
            onRejected: ((error: NullishType) => E|PromiseLike<E> throws)|undefined): PromiseLike<U|E>;
}

// 定义fulfilled状态时的接口类型
export class PromiseFulfilledResult<T> {
    status: string;
    value: T;
}
// 定义rejected状态时的接口类型
export class PromiseRejectedResult {
    status: string;
    reason: NullishType;
}

export type PromiseSettledResult<T> = PromiseFulfilledResult<T>|PromiseRejectedResult

/**
 * Class represents a result of an asynchronous operation in the future.
 * Promise是一个类
 */
export final class Promise<out T> implements PromiseLike<T> {
    private constructor() {
    }
    // 可以接收只有resolve回调的函数
    constructor(callback: (resolve: (value: T|PromiseLike<T>) => void) => void throws) {
        try {
            callback((value: T|PromiseLike<T>): void => {
                this.doResolve<T>(value);
            });
        } catch (error) {
            this.rejectImpl(error);
        }
    }

    // NOTE(audovichenko): add constructor #17147
    // constructor(callback: (resolve: (value: T|PromiseLike<T>) => void throws,
    //        reject: () => void) => void throws)
    constructor(callback: (resolve: (value: T|PromiseLike<T>) => void throws,
            reject: (error: NullishType) => void) => void throws) {
        try {
			// 初始化Promise的时候,立即调用callback
            callback((value: T|PromiseLike<T>): void => {
 				// 外部调用resolve的时候,内部调用doResolve
                this.doResolve<T>(value);
            }, (error: NullishType): void => {
				// 外部调用reject的时候,内部调用rejectImpl
                this.rejectImpl(error);
            });
        } catch (error) {
			// 如果执行callback的过程中报错,Promise立马转为rejected状态
            this.rejectImpl(error);
        }
    }

    // NOTE(audovichenko): Change return type to Promise<U>. Issue #15523
    // then的回调函数不包含参数
    then<U>(onFulfilled: () => U|PromiseLike<U> throws): PromiseLike<U> {
        // 调用then方法的时候,内部会生成一个Promise并返回
        let promise = new Promise<U>();
        
        // 将then的参数封装成fn
        let fn: () => void = (): void => {
            try {
                if (this.state == Promise.STATE_RESOLVED) {
                    promise.doResolve<U>(onFulfilled());
                } else {
                    promise.rejectImpl(this.value);
                }
            } catch (error) {
                promise.rejectImpl(error);
            }
        }
		// 如果此时promise的状态不是pendding,说明状态已经变成了最终值fulfilled或者rejected。
        // 直接添加到微任务队列,微任务队列的任务会一直执行直到清空
        if (this.state != Promise.STATE_PENDING) {
            Promise.addToJobQueue(fn as Object);
        } else {
			// 如果此时promise的状态还是pendding,将fn添加到then状态队列
            this.pushToThenQueue(fn as Object);
        }
        return promise;
    }
    // then的回调函数包含一个参数
    // NOTE(audovichenko): Change return type to Promise<U>. Issue #15523
    then<U>(onFulfilled: (value: T) => U|PromiseLike<U> throws): PromiseLike<U> {
        let promise = new Promise<U>();
        let fn: () => void = (): void => {
            try {
                if (this.state == Promise.STATE_RESOLVED) {
                    // 回调的时候将this.value回传
                    promise.doResolve<U>(onFulfilled(this.value!));
                } else {
                    promise.rejectImpl(this.value! as Object);
                }
            } catch (e) {
                promise.rejectImpl(e);
            }
        }
        if (this.state != Promise.STATE_PENDING) {
            Promise.addToJobQueue(fn as Object);
        } else {
            this.pushToThenQueue(fn as Object);
        }
        return promise;
    }

    // NOTE(audovichenko): Change return type to Promise<U>. Issue #15523
    // NOTE(audovichenko): Mark parameters by '?' instead of add '|undefined'. Issue #17204
    // 传入两个参数的then方法
    then<U, E = never>(onFulfilled: ((value: T) => U|PromiseLike<U> throws)|undefined,
            onRejected: ((error: NullishType) => E|PromiseLike<E> throws)|undefined): PromiseLike<U|E> {
        let promise = new Promise<U|E>();
        // 封装一个箭头函数作为微任务的一个任务
        let fn: () => void = (): void => {
            try {
			    // 如果是resolved状态
                if (this.state == Promise.STATE_RESOLVED) {
                    // 如果then方法里传了onFulfilled回调函数,则把onFulfilled的结果值作为参数后调用doResolve
                    if (onFulfilled) {
                        promise.doResolve<U>(onFulfilled(this.value!));
                    } else {
                        promise.resolveImpl(this.value!);
                    }
                } else {
                    // 如果then方法里传了onRejected回调函数,则把onRejected的结果值作为参数后调用rejectImpl
                    if (onRejected) {
                        promise.rejectImpl(onRejected(this.value! as Object));
                    } else {
                        promise.rejectImpl(this.value!);
                    }
                }
            } catch (e) {
                promise.rejectImpl(e);
            }
        }
        // 如果已经变了状态,添加到微任务队列。在队列中任务执行的时候会在fn中判断状态
        if (this.state != Promise.STATE_PENDING) {
            Promise.addToJobQueue(fn as Object);
        } else {
            // pending状态下,直接将函数入队即可。因为此时promise还没变状态
            this.pushToThenQueue(fn as Object);
            this.pushToCatchQueue(fn as Object);
        }
        return promise;
    }
    // catch方法
    catch<U = never>(onRejected?: (error: NullishType) => U|PromiseLike<U> throws): Promise<T|U> {
        // 声明一个新的promise 并最终将这个promise返回
        let promise = new Promise<T|U>();
        // 封装一个任务
        let fn: () => void = (): void => {
            try {
                // 如果传入了onRejected,将onRejected的返回值作为参数调用doResolve,将本状态修改为resolved
				// 所以即使onRejected是一个错误回调。Promise也仍然将它视作一个正常值
                if (onRejected) {
                    let res: U|PromiseLike<U> = onRejected(this.value);
                    promise.doResolve<U>(res);
                } else {
                    promise.rejectImpl(this.value!);
                }
            } catch (e) {
                promise.rejectImpl(e);
            }
        }
        // 判断是否已经是rejected,如果是则将任务添加到微任务队列
        if (this.state == Promise.STATE_REJECTED) {
            Promise.addToJobQueue(fn as Object);
        } else if (this.state == Promise.STATE_PENDING) {
            // 如果还处于pending状态,把封装的任务放到catchQueue中
            this.pushToCatchQueue(fn as Object);
        }
        return promise;
    }
    // finally和then、catch方法一样,都会返回一个新的Promise
    finally(onFinally?: () => void throws): Promise<T> {
        let promise = new Promise<T>();
        let fn: () => void = (): void => {
            try {// 如果onFinally传入了参数,就执行传入的参数
                if (onFinally) {
                    try {
                        onFinally();
                    } catch(error) {
						// 如果执行出错,则新的promise状态变为rejected
                        promise.rejectImpl(error);
                    }
                }
                // 根据当前Promise的不同状态执行 新promise的resolve或reject
                if (this.state == Promise.STATE_RESOLVED) {
                    promise.resolveImpl(this.value!);
                } else {
                    promise.rejectImpl(this.value! as Object);
                }
            } catch (e) {
                promise.rejectImpl(e);
            }
        }
        // 和then、catch一样。pending状态推入各自的回调队列。非pending状态将任务推入微任务队列
        if (this.state != Promise.STATE_PENDING) {
            Promise.addToJobQueue(fn as Object);
        } else {
            this.pushToThenQueue(fn as Object);
            this.pushToCatchQueue(fn as Object);
        }
        return promise;
    }
    // 返回一个resolved状态的promise
    static resolve(): Promise<void> {
        let p = new Promise<void>();
        p.resolveImpl(undefined);
        return p;
    }

    static resolve<U>(value: U|PromiseLike<U>): Promise<U> {
        let p = new Promise<U>();
        p.doResolve(value);
        return p;
    }

    static reject(): Promise<void> {
        let p = new Promise<void>();
        p.rejectImpl(null);
        return p;
    }
    // 返回一个rejected状态的promise
    static reject<U = never>(value: U): Promise<U> {
        let p = new Promise<U>();
        p.rejectImpl(value);
        return p;
    }

    static all<U>(promises: (U|PromiseLike<U>)[]): Promise<U[]> {
        return new Promise<U[]>((resolve: (value: U[]) => void, reject: (error: NullishType) => void): void => {
            // This temp object is needed because es2panda cannot change captured primitives
            new AllPromiseConcurrency<U>(resolve, reject).all(promises);
        });
    }

    static all<U>(promises: Iterable<U|PromiseLike<U>>): Promise<U[]> {
        return Promise.all<U>(Promise.toArray(promises));
    }

    static allSettled<U>(promises: (U|PromiseLike<U>)[]): Promise<PromiseSettledResult<U>[]> {
        return new Promise<PromiseSettledResult<U>[]>((resolve: (value: PromiseSettledResult<U>[]) => void, reject: (error: NullishType) => void): void => {
            // This temp object is needed because es2panda cannot change captured primitives
            new AllSettledPromiseConcurrency<U>(resolve, reject).allSettled(promises);
        });
    }

    static allSettled<U>(promises: Iterable<U|PromiseLike<U>>): Promise<PromiseSettledResult<U>[]> {
        return Promise.allSettled<U>(Promise.toArray(promises));
    }

    static any<U>(promises: (U|PromiseLike<U>)[]): Promise<U> {
        return new Promise<U>((resolve: (value: U) => void, reject: (error: NullishType) => void): void => {
            // This temp object is needed because es2panda cannot change captured primitives
            new AnyPromiseConcurrency<U>(resolve, reject).any(promises);
        });
    }

    static any<U>(promises: Iterable<U|PromiseLike<U>>): Promise<U> {
        return Promise.any<U>(Promise.toArray(promises));
    }
    // 每一个同名重载方法,都接受迭代器类型和数组类型
    static race<U>(promises: (U|PromiseLike<U>)[]): Promise<U> {
        return new Promise<U>((resolve: (value: U) => void, reject: (error: NullishType) => void): void => {
            // This temp object is needed because es2panda cannot change captured primitives
            new RacePromiseConcurrency<U>(resolve, reject).race(promises);
        });
    }

    static race<U>(promises: Iterable<U|PromiseLike<U>>): Promise<U> {
        return Promise.race<U>(Promise.toArray(promises));
    }
    
    // 将迭代器转换成数组
    private static toArray<U>(values: Iterable<U>): U[] {
        let it = values.iterator();
        let v = it.next();
        // 如果迭代器一个元素都没有,返回一个空数组
        if (v.done) {
            return new U[0];
        }
        let array: U[] = new U[1];
        array[0] = v.value!;
        let len = 1;
        while (true) {
            v = it.next();
            if (v.done) {
                return Promise.trim(array, len);
            }
            array = Promise.ensureCapacity(array, len + 1);
            array[len] = v.value!;
            ++len;
        }
    }
    
    // 数组缩容操作。如果满了就不缩容。否则重新生成一个数组,并将原数组拷贝过去
    private static trim<U>(array: U[], length: int): U[] {
        if (array.length == length) {
            return array;
        }
        let result = new U[length];
        for (let i = 0; i < length; ++i) {
            result[i] = array[i];
        }
        return result;
    }

    // 确保数组至少有size的容量
    private static ensureCapacity<U>(queue: U[], size: int): U[] {
        // 说明size所在的下标还可以存储数据
        if (size <= queue.length) {
            return queue;
        }
        // 进行两倍的扩容
        let newQueue = new U[size * 2];
        for (let i = 0; i < queue.length; ++i) {
            newQueue[i] = queue[i];
        }
        return newQueue;
    }

    // 推入到then队列
    private pushToThenQueue(job: Object): void {
        // 保证this.catchQueue一定存在
        // length property of thenQueue Objet array represents its capacity, thenQueueSize represents its current size
        if (this.thenQueue == null) {
            this.thenQueue = Promise.EMPTY_QUEUE;
        }
        // 保证数组可以存放对应位置的job。ensureCapacity会做一些扩容
        this.thenQueue = this.ensureCapacity(this.thenQueue!, this.thenQueueSize + 1);
        this.thenQueue![this.thenQueueSize] = job;
        ++this.thenQueueSize;
    }
    
    // 推入到catch队列
    private pushToCatchQueue(job: Object): void {
        // 保证this.catchQueue一定存在
        // length property of catchQueue Objet array represents its capacity, catchQueueSize represents its current size
        if (this.catchQueue == null) {
            this.catchQueue = Promise.EMPTY_QUEUE;
        }
        // 保证数组可以存放对应位置的job。ensureCapacity会做一些扩容
        this.catchQueue = this.ensureCapacity(this.catchQueue!, this.catchQueueSize + 1);
        this.catchQueue![this.catchQueueSize] = job;
        ++this.catchQueueSize;
    }
    // 如果参数是一个Promise。本Promise的状态和参数Promise的状态保持一致
    private subscribeOnAnotherPromise<U>(internalPromise: PromiseLike<U>): void {
        let thisPromise = this;
		// 本Promise的状态和参数Promise的状态保持一致
        internalPromise.then<void, void>((value: U): void => {
            thisPromise.resolveImpl(value);
        }, (error: NullishType): void => {
            thisPromise.rejectImpl(error);
        });
    }

    // 执行resolve动作
    private doResolve<U>(value: U|PromiseLike<U>): void {
        if (value instanceof PromiseLike) {
            this.subscribeOnAnotherPromise<U>(value as PromiseLike<U>);
        } else {
            this.resolveImpl(value);
        }
    }

    // 一些native实现的方法
    public native awaitResolution(): T;
  
    private native resolveImpl<U>(value: U): void;
    private native rejectImpl(error: NullishType): void;
    private static native addToJobQueue(job: Object): void;

    // pendding、fulfilled、rejected状态定义
    private static STATE_PENDING = 0;
    private static STATE_RESOLVED = 1;
    private static STATE_REJECTED = 2;
    private static EMPTY_QUEUE = new Object[0];

    // Order of fields should be the following
    // 1. Reference fields
    // 2. Primitive fields in mostly size decreasing order
    // filling alignment holes
    // resolve时的返回值
    private value: T | null = null;
    // then方法传入的回调函数的数组
    private thenQueue: Object[]|null = null;
    // catch方法传入的回调函数的数组
    private catchQueue: Object[]|null = null;
    private linkedPromise: Object | null = null;
    private eventPtr: long;
    private thenQueueSize: int = 0;
    private catchQueueSize: int = 0;
    // Promise内的状态
    private state: int = Promise.STATE_PENDING;
}

class PromiseConcurrencyBase<T> {
    // 如果是PromiseLike直接返回,否则将值包装到Promise.resolve中
    toPromiseLike(value: T|PromiseLike<T>): PromiseLike<T> {
        if (value instanceof PromiseLike) {
            let p = value as PromiseLike<T>;
            return p;
        } else {
            let p = Promise.resolve<T>(value as T);
            return p;
        }
    }
}

class AllPromiseConcurrency<T> extends PromiseConcurrencyBase<T> {
    constructor(resolve: (value: T[]) => void, reject: (error: NullishType) => void) {
        this.resolve = resolve;
        this.reject = reject;
    }
    // Promiase.all的实现
    all(promises: (T|PromiseLike<T>)[]): void {
        this.values = new T[promises.length];
        if (promises.length == 0) {
            this.resolve(this.values!);
            return;
        }
        for (let i = 0; i < promises.length; ++i) {
            let idx = i;
            this.toPromiseLike(promises[idx]).then<void, void>((value: T): void => {
                this.resolveImpl(value, idx);
            }, (error: NullishType): void => {
                // 只要有一个失败,就失败
                this.reject(error);
            });
        }
    }
    // 成功时使用resolvedCnt统计数量,总数量和promises数量相等时回调
    private resolveImpl(value: T, idx: int): void {
        this.values![idx] = value;
        ++this.resolvedCnt;
        if (this.resolvedCnt == this.values!.length) {
            this.resolve(this.values!);
        }
    }

    private resolvedCnt = 0;
    private rejectedCnt = 0;
    private values: T[]|null = null;
    private resolve: (value: T[]) => void;
    private reject: (error: NullishType) => void;
}

class AllSettledPromiseConcurrency<T> extends PromiseConcurrencyBase<T> {
    constructor(resolve: (value: PromiseSettledResult<T>[]) => void, reject: (error: NullishType) => void) {
        this.resolve = resolve;
        this.reject = reject;
    }
    // Promiase.allSettled的实现
    allSettled(promises: (T|PromiseLike<T>)[]): void {
        this.values = new PromiseSettledResult<T>[promises.length];
        if (promises.length == 0) {
            this.resolve(this.values!);
            return;
        }
        for (let i = 0; i < promises.length; ++i) {
            let idx = i;
            this.toPromiseLike(promises[idx]).then<void, void>((value: T): void => {
                this.resolveImpl(value as T, idx);
            }, (error: NullishType): void => {
                this.rejectImpl(error, idx);
            });
        }
    }
	// 成功和失败,都使用resolvedCnt统计数量,总数量和promises数量相等时回调
    private resolveImpl(value: T, idx: int): void {
        let res = new PromiseFulfilledResult<T>();
        res.status = "fulfilled";
        res.value = value;
        this.values![idx] = res;
        ++this.resolvedCnt;
        if (this.resolvedCnt == this.values!.length) {
            this.resolve(this.values!);
        }
    }
    // 成功和失败,都使用resolvedCnt统计数量,总数量和promises数量相等时回调
    private rejectImpl(error: NullishType, idx: int): void {
        let res = new PromiseRejectedResult();
        res.status = "rejected";
        res.reason = error;
        this.values![idx] = res;
        ++this.resolvedCnt;
        if (this.resolvedCnt == this.values!.length) {
            this.resolve(this.values!);
        }
    }

    private resolvedCnt = 0;
    private rejectedCnt = 0;
    private values: PromiseSettledResult<T>[]|null = null;
    private resolve: (value: PromiseSettledResult<T>[]) => void;
    private reject: (error: NullishType) => void;
}

class AnyPromiseConcurrency<T> extends PromiseConcurrencyBase<T> {
    constructor(resolve: (value: T) => void, reject: (error: NullishType) => void) {
        this.resolve = resolve;
        this.reject = reject;
    }
	// Promiase.any的实现
    any(promises: (T|PromiseLike<T>)[]): void {
        this.errors = new Error[promises.length];
        if (promises.length == 0) {
            this.reject(new AggregateError(this.errors!, "All promises are rejected"));
            return;
        }
        for (let i = 0; i < promises.length; ++i) {
            let idx = i;
            this.toPromiseLike(promises[idx]).then<void, void>((value: T): void => {
                this.resolveImpl(value as T);
            }, (error: NullishType): void => {
                this.rejectImpl(error, idx);
            });
        }
    }

    // 只要一个成功,就算成功
    private resolveImpl(value: T) {
        ++this.resolvedCnt;
        if (this.resolvedCnt == 1) {
            this.resolve(value);
        }
    }
    // 统计失败的数量,全部失败,才算失败
    private rejectImpl(error: NullishType, idx: int) {
        ++this.rejectedCnt;
        if (error == null || error instanceof Error) {
            this.errors![idx] = error as Error;
        } else {
            this.errors![idx] = new Error(error!.toString());
        }
        if (this.rejectedCnt == this.errors!.length) {
            this.reject(new AggregateError(this.errors!, "All promises are rejected"));
        }
    }

    private resolvedCnt = 0;
    private rejectedCnt = 0;
    private errors: Error[]|null = null;
    private resolve: (value: T) => void;
    private reject: (error: NullishType) => void;
}

class RacePromiseConcurrency<T> extends PromiseConcurrencyBase<T> {
    constructor(resolve: (value: T) => void, reject: (error: NullishType) => void) {
        this.resolve = resolve;
        this.reject = reject;
    }
	// Promise.race方法的实现
    race(promises: (T|PromiseLike<T>)[]): void {
 		// 遍历传入的promise,只要有一个状态发生变化。this的状态就发生变化,同时settled设置为true
        for (let i = 0; i < promises.length; ++i) {
            let idx = i;
            this.toPromiseLike(promises[idx]).then<void, void>((value: T): void => {
                this.resolveImpl(value as T);
            }, (error: NullishType): void => {
                this.rejectImpl(error);
            });
        }
    }
	// 只要成功,就将settled置为true
    private resolveImpl(value: T) {
        if (!this.settled) {
            this.resolve(value)
            this.settled = true;
        }
    }
    // 只要失败,就将settled置为true
    private rejectImpl(error: NullishType) {
        if (!this.settled) {
            this.reject(error);
            this.settled = true;
        }
    }

    private settled = false;
    private resolve: (value: T) => void;
    private reject: (error: NullishType) => void;
}

export type NullablePromise<out T> = Promise<T> | null;

resolveImpl、rejectImpl、addToJobQueue

我们从上面最常规的Promise类里面没有发现这几个函数的实现。全局搜索一下发现他们有对应的原生实现

image.png

resolveImpl
void EtsPromiseResolve(EtsPromise *promise, EtsObject *value)

这个方法里面也判断了value,如果value是一个Promise,本Promise的结果是依赖于value这个Promise的

最终会调用hpromise→Resolve(coro, value)修改Promise的状态,之后遍历执行thenQueue中存放的回调

image.png

void Resolve(EtsCoroutine *coro, EtsObject *value)

这里主要是修改了Promise的状态为Resolved,同时把成功的值放入到promise中

image.png

static void OnPromiseCompletion(EtsCoroutine *coro, EtsHandle &promise, EtsHandle &queue, EtsInt length)

OnPromiseCompletion中完成对thenQueue队列的处理,遍历队列里的每一个回调,然后执行

image.png

rejectImpl
void EtsPromiseReject(EtsPromise *promise, EtsObject *error)

调用hpromise->Reject(coro, error)  修改Promise的状态为rejected,然后遍历catchQueue进行回调函数的调用

然后调用OnPromiseCompletion完成对catchQueue的遍历回调。

可以看到不管是resolve还是reject,最终都是调用了OnPromiseCompletion。为什么resolve和reject都能调用OnPromiseCompletion,是因为入队的元素都是被包装过的箭头函数

image.png

void Reject(EtsCoroutine *coro, EtsObject *error)

主要是修改了状态为Rejected,同时把值塞入到error中

image.png

addToJobQueue

可以看到最终只是把回调添加到了jobQueue里面。这个jobQueue就是用于存放微任务的队列

image.png

void EtsPromiseAddToJobQueue(EtsObject *callback)

添加到微任务队列,主要是调用了jobQueue的AddJob方法

image.png

void JsJobQueue::AddJob(EtsObject *callback)

可以看到添加到微任务队列的任务,在最底层又被C API包装成了一个promise,原有的任务会在这个promise对象的then方法回调中执行

image.png

static napi_value ThenCallback(napi_env env, napi_callback_info info)

ThenCallback这个函数实际上就是调用了上一步封装好的callbackRef

image.png

Ets中的setTimeout、setInternal

Ets中setTimeout和setInternal的实现位于 gitee.com/openharmony… 中

void JsiTimerModule::InitTimerModule(const shared_ptr& runtime, shared_ptr& moduleObj)

image.png

setTimeout和setInternal都是使用 SetTimeoutOrInterval 实现的

image.png

shared_ptr SetTimeoutOrInterval(const shared_ptr& runtime, const shared_ptr& thisObj, const std::vector<shared_ptr>& argv, int32_t argc, bool isInterval)

image.png

uint32_t JsiTimerModule::AddCallBack(const shared_ptr& func, const std::vector<shared_ptr>& params)

按照callbackId存储到两个对应的Map中

image.png

void ClearTimeoutOrInterval(const shared_ptr& runtime, const shared_ptr& thisObj, const std::vector<shared_ptr>& argv, int32_t argc)

clear方法根据传入的callbackId,将回调以及参数从对应的Map中移除

image.png

分析代码执行

宏任务、微任务 

    async function async1() {
  console.log('t111 async1 start');
  await async2();
  console.log('t111 async1 end');
}
async function async2() {
  console.log('t111 async2');
}
console.log('t111 script start');
setTimeout(()=> {
  console.log('t111 setTimeout');
}, 0)
async1();
new Promise<void>((resolve) =>{
  console.log('t111 promise1');
  resolve();
}).then(() =>{
  console.log('t111 promise2');
});
console.log('t111 script end');
/**
06-06 14:02:26.533   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 script start
06-06 14:02:26.533   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 async1 start
06-06 14:02:26.533   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 async2
06-06 14:02:26.533   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 promise1
06-06 14:02:26.533   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 script end
06-06 14:02:26.534   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 async1 end
06-06 14:02:26.534   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 promise2
06-06 14:02:26.542   22305-22305  A03D00/JSAPP                   pid-22305             I     t111 setTimeout
*/

先执行宏任务(当前代码块也算是宏任务),然后执行当前宏任务产生的微任务,然后接着执行宏任务

  1. 从上往下执行代码,先执行同步代码,输出 t111 script start
  2. 遇到setTimeout,把 setTimeout 的代码放到宏任务队列中
  3. 执行 async1(),输出 t111 async1 start, 然后执行 async2(), 输出 t111 async2,把 async2() 后面的代码 console.log('t111 async1 end')放到微任务队列中
  4. 接着往下执行,输出 promise1,把 .then()放到微任务队列中;注意Promise本身是同步的立即执行函数,.then是异步执行函数
  5. 接着往下执行, 输出 t111 script end。同步代码(同时也是宏任务)执行完成,接下来开始执行刚才放到微任务中的代码
  6. 依次执行微任务中的代码,依次输出 t111 async1 end、 t111 promise2, 微任务中的代码执行完成后,开始执行宏任务中的代码,输出 t111 setTimeout

宏任务产生微任务

    console.log('t222 start');
setTimeout(() => {
  console.log('t222 children2');
  Promise.resolve().then(() => {
    console.log('t222 children3');
  })
}, 0);

new Promise<string>((resolve, reject) =>{
  console.log('t222 children4');
  setTimeout(() =>{
    console.log('t222 children5');
    resolve('t222 children6')
  }, 0)
}).then((res) => {
  console.log('t222 children7');
  setTimeout(() => {
    console.log(res);
  }, 0)
})
/**
06-06 14:05:16.276   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 start
06-06 14:05:16.277   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 children4
06-06 14:05:16.284   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 children2
06-06 14:05:16.284   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 children3
06-06 14:05:16.284   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 children5
06-06 14:05:16.284   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 children7
06-06 14:05:16.284   23368-23368  A03D00/JSAPP                   pid-23368             I     t222 children6
*/
  1. 从上往下执行代码,先执行同步代码,输出 t222 start
  2. 遇到setTimeout,把 setTimeout 的代码放到宏任务队列①中
  3. 接着往下执行,输出 t222 children4, 遇到setTimeout,把 setTimeout 的代码放到宏任务队列②中,此时.then并不会被放到微任务队列中,因为 resolve是放到 setTimeout中执行的
  4. 代码执行完成之后,会查找微任务队列中的事件,发现并没有,于是开始执行宏任务①,即第一个 setTimeout, 输出 t222 children2,此时,会把 Promise.resolve().then放到微任务队列中。
  5. 宏任务①中的代码执行完成后,会查找微任务队列,于是输出 t222 children3;然后开始执行宏任务②,即第二个 setTimeout,输出 t222 children5,此时将.then放到微任务队列中。
  6. 宏任务②中的代码执行完成后,会查找微任务队列,于是输出 t222 children7,遇到 setTimeout,放到宏任务队列中。此时微任务执行完成,开始执行宏任务,输出 t222 children6;

微任务产生宏任务

    // 1. js全局上下文入栈,遇到new Promise()同步任务执行打印promise1 resolve()后 .then异步函数被推入微任务队列
new Promise<void>((resolve, reject) => {
  console.log('t333 promise1')
  resolve()
}).then(() => {
  // 8. 执行完当前主线程后依次执行当前微任务队列、直至清空、队列的结构是先进先出、所以依次如下
  // 执行第一个微任务打印promise2
  console.log('t333 promise2')
})
// 2. 遇到console.log('start1')同步立即执行打印start1
console.log('t333 start1')
// 3. 遇到setTimeout 异步任务2s后把要执行的任务推入宏任务队列中
setTimeout(() => {
  // 16. 打印a
  console.log('t333 a')
},2000)
// 4. 遇到setTimeout 异步任务1s后把要执行的任务推入宏任务队列中
setTimeout(() => {
  // 15. 打印b
  console.log('t333 b')
},1000)
// 5. 遇到setTimeout 异步任务立即把要执行的任务推入宏任务队列中
setTimeout(() => {
  // 11. 遇到promsie.resolve()执行将then方法推入微任务队列
  Promise.resolve().then(() => {
    // 清空当前微任务队列打印promiseA 将后面的then又推入微任务队列
    console.log('t333 promiseA')
  }).then(() => {
    // 12. 清空当前微任务队列打印promiseB
    // 判断当前微任务队列是否为空、为空将下一个宏任务入栈并执行
    console.log('t333 promiseB')
  })
})
// 6. 遇到Promise执行resolve后将第一个then方法推入微任务队列中
Promise.resolve().then(() => {
  // 9. 执行第二个微任务打印promise88
  console.log('promise88')
  // 紧接着遇到setTimeout 异步任务立即把要执行的任务推入宏任务队列中、将后面的then推入微任务队列中
  setTimeout(() => {
    // 13. 打印333
    console.log("t333 333")
  })
}).then(() => {
  // 10. 执行第三个微任务打印promise2。
  console.log('promise2')
  // 紧接着遇到setTimeout 异步任务立即把要执行的任务推入宏任务队列中
  // 检查当前微任务队列是否为空、为空将宏任务队列中的下一个入栈执行
  setTimeout(() => {
    // 14. 打印555
    console.log("t333 555")
  })
})
// 7. 遇到console.log('start2')执行打印start2。此时打印了 promise1、start1、start2
console.log('t333 start2')
/**
06-12 22:12:12.849   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 promise1
06-12 22:12:12.849   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 start1
06-12 22:12:12.849   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 start2
06-12 22:12:12.849   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 promise2
06-12 22:12:12.849   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 promise88
06-12 22:12:12.856   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 promiseA
06-12 22:12:12.856   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 promiseB
06-12 22:12:12.856   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 333
06-12 22:12:12.856   15723-15723  A03D00/JSAPP                   pid-15723             I     t333 555
06-12 22:12:13.851   15723-15723  A03D00/JSAPP                   com.unrav...lication  I     t333 b
06-12 22:12:14.849   15723-15723  A03D00/JSAPP                   com.unrav...lication  I     t333 a
*/

微任务产生微任务

    // 1. Promise.sesolve创建了一个fulfilled状态的promise,然后调用then方法,将then的参数放入到微任务队列
Promise.resolve().then(() => {
  console.log('t444 0');
  // 如果then里面返回了一个promise,那么then本身返回的promise的结果依赖then方法返回的promise的结果。
  // 相当于间接增加了一个微任务Job
  return Promise.resolve('t444 4');
}).then((res) => {
  // 如果then方法接受一个参数,并且这个参数是一个Promise的时候
  console.log(res)
})
// 2. Promise.sesolve创建了一个fulfilled状态的promise,然后调用then方法,将then的参数放入到微任务队列
Promise.resolve().then(() => {
  console.log('t444 1');
}).then(() => {
  console.log('t444 2');
}).then(() => {
  console.log('t444 3');
}).then(() => {
  console.log('t444 5');
}).then(() =>{
  console.log('t444 6');
})

/**
06-07 13:13:15.029   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 0
06-07 13:13:15.030   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 1
06-07 13:13:15.030   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 2
06-07 13:13:15.030   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 3
06-07 13:13:15.030   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 4
06-07 13:13:15.030   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 5
06-07 13:13:15.030   20470-20470  A03D00/JSAPP                   com.unrav...lication  I     t444 6
*/

参考资料

  1. MDN - Promise developer.mozilla.org/zh-CN/docs/…
  2. Promise对象 https://wangdoc.com/es6/promise
  3. Generator函数的语法 wangdoc.com/es6/generat…
  4. Generator函数的异步应用 wangdoc.com/es6/generat…
  5. Symbol https://wangdoc.com/es6/symbol
  6. async 函数 wangdoc.com/es6/async
  7. 异步遍历器 wangdoc.com/es6/async-i…
  8. PromiseA+规范[ promisesaplus.com/]promisesaplus.com/)
  9. PromiseA+规范中文翻译版 www.ituring.com.cn/article/665…
  10. Dart中的生成器 https://dart.cn/language/functions#generators
  11. Ark编译器核心 https://gitee.com/openharmony/arkcompiler_runtime_core
  12. Ark引擎 https://gitee.com/openharmony/arkui_ace_engine
  13. 八段代码彻底掌握 Promise juejin.cn/post/684490…
  14. 从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节 juejin.cn/post/694531… 15.【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理) juejin.cn/post/684490…
  15. 9k字 | Promise/async/Generator实现原理解析 juejin.cn/post/684490…
  16. 2K字就能理解的async/await原理,还要拖多久?segmentfault.com/a/119000004…
  17. 面试官:“你能手写一个 Promise 吗” https://zhuanlan.zhihu.com/p/183801144
  18. 图解 Promise 实现原理(一)—— 基础实现 zhuanlan.zhihu.com/p/58428287