Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

模拟实现一个async #46

Open
guapi233 opened this issue Jan 7, 2021 · 0 comments
Open

模拟实现一个async #46

guapi233 opened this issue Jan 7, 2021 · 0 comments
Labels

Comments

@guapi233
Copy link
Owner

guapi233 commented Jan 7, 2021

async/await可以让一段异步代码同步执行,但是这段异步代码整体还是异步的:

asyncFn(); // asyncFn是异步代码,但是它里面的内容可以同步执行
otherFn(); // 因为asyncFn是异步,所以otherFn()会先出结果(不是异步)

效果

直接上效果代码:

const runner = main(function* (param) {
  console.log(param);
  let a = yield 3;
  let b = yield 4;
  let c = yield new Promise((resolve, reject) =>
    setTimeout(resolve, 3000, [5, 6, 7])
  );
  let d = yield Promise.resolve(6);

  return [a, b, c, d];
});

runner("ree").then((res) => {
  console.log(res); // [3, 4, [5, 6, 7], 6];
});

原理

function main(fn) {
  return (...params) => {
    const gen = fn(...params);

    return new Promise((resolve, reject) => {
      function _next(...params) {
        step(gen, resolve, reject, _next, _throw, "next", params);
      }

      function _throw(err) {
        step(gen, resolve, reject, _next, _throw, "throw", [err]);
      }

      _next();
    });
  };
}

function step(gen, resolve, reject, _next, _throw, key, param) {
  const { value, done } = gen[key](...param);

  try {
    if (done) {
      resolve(value);
    } else {
      Promise.resolve(value).then(_next, _throw);
    }
  } catch (err) {
    reject(err);
  }
}

原理就是运用了generator可以中止函数执行的特性,在遇到yield时退出等待异步执行完毕时再回到函数中继续向下执行,async/await只是作为一种语法糖,将我们需要手动调用next的步骤省略了。而且还给async函数本身套上了一层Promise,使这个函数能够“自个玩自个的”,不会阻塞函数外的代码。

参考

@guapi233 guapi233 added the 笔记 label Jan 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant