> For the complete documentation index, see [llms.txt](https://1425816423.gitbook.io/my-knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://1425816423.gitbook.io/my-knowledge-base/qian-duan-ji-shu/javascript/async-han-shu-de-polyfill.md).

# async函数的polyfill

tags: JavaScript Created time: July 17, 2023 9:15 PM

async函数本身是generator的语法糖，在不支持async函数的场景下可以使用genrator函数来实现async函数的效果。

假设有以下代码：

```tsx
function wait1() {
  return new Promise((r) => {
    setTimeout(() => {
      r('result1');
    }, 1000);
  });
}

function wait2() {
  return new Promise((r) => {
    setTimeout(() => {
      r('result2');
    }, 1000);
  });
}
```

我们需要先执行wait1并等待返回结果，之后再执行wait2等待返回结果，如果使用async函数，那么这将非常简单：

```tsx
async fn(){
	const res1 = await wait1();
	const res2 = await wait2()
}
```

当时在不支持异步函数的环境下，需要用generator函数来实现相似的效果。

首先yield关键子可以“暂停”函数的执行，并取得其后的返回值，这和await很像，但是区别在于await能够等到其后函数异步完成后继续执行async函数，而yield需要我们自己手动判断什么时候需要继续执行函数，由于wait函数返回是Promise，因此我们需要一个额外的函数辅助，当wait的promise进入resolve状态时，就是generaotr函数继续执行的时刻。

完整代码如下：

```tsx
function wait1() {
  return new Promise((r) => {
    setTimeout(() => {
      r('result1');
    }, 1000);
  });
}

function wait2() {
  return new Promise((r) => {
    setTimeout(() => {
      r('result2');
    }, 1000);
  });
}

// 模拟async函数
function* asyncFn() {
  const result1 = yield wait1();
  console.log('wait1执行完了', result1);
  const result2 = yield wait2();
  console.log('wait2执行完了', result2);
  return [result1, result2];
}

// 由于generator函数不能自动执行，因此需要一个辅助函数管理执行状态
function runFn(generator) {
  const g = generator();

  function handleNext(iterator) {
    if (iterator.done) {
      return Promise.resolve(iterator.value);
    }

    return Promise.resolve(iterator.value)
      .then((e) => handleNext(g.next(e)))
      .catch((e) => handleNext(g.throw(e)));
  }

  try {
    return handleNext(g.next());
  } catch (err) {
    throw err;
  }
}

runFn(asyncFn)
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.error(err);
  });

// wait1执行完了 result1
// wait2执行完了 result2
// ['result1', 'result2']
```
