# 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']
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://1425816423.gitbook.io/my-knowledge-base/qian-duan-ji-shu/javascript/async-han-shu-de-polyfill.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
