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

await async 如何实现 #280

Open
lxy-Jason opened this issue Nov 6, 2022 · 2 comments
Open

await async 如何实现 #280

lxy-Jason opened this issue Nov 6, 2022 · 2 comments

Comments

@lxy-Jason
Copy link
Contributor

lxy-Jason commented Nov 6, 2022

function asyncToGenerator(generatorFunc) {
  //传入一个生成器函数
  //返回一个新的函数
  return function () {
    //先调用generator函数生成<迭代器>
    const gen = generatorFunc.apply(this, arguments);
    //返回一个promise
    return new Promise((resolve, reject) => {
      //内部定义一个step函数来源 用来一步步跨过yield的阻碍
      //key有next和throw两种取值,分别对应了gen的next和throw方法
      //arg参数则是用来promise resolve得带的值交给下一个yield
      function step(key, arg) {
        let generatorResult;

        try {
          generatorResult = gen[key](arg);
        } catch (err) {
          return reject(err);
        }
        //gen.next()得到的结果是一个{value,done}的结构
        const { value, done } = generatorResult;
        if (done) {
          //已经完成
          return resolve(value);
        } else {
          return Promise.resolve(
            //对value不是promise的情况包裹一层
            value //这个value对应的是yield后面的promise
          ).then(
            function onResolve(val) {
              step("next", val);
            },
            function onReject(err) {
              step("throw", err);
            }
          );
        }
      }
      step("next"); //第一次调用next
    });
  };
}
function fn(nums) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(nums * 2);
    }, 1000);
  });
}
function* gen() {
  const num1 = yield fn(1);
  console.log(num1); // 2
  const num2 = yield fn(num1);
  console.log(num2); // 4
  const num3 = yield fn(num2);
  console.log(num3); // 8
  return num3;
}
const testGAsync = asyncToGenerator(gen);
// 返回的是一个函数,函数调用返回一个promise
testGAsync().then(res => {
    console.log(res);
});
//对应上面的gen()
async function asyncFn() {
  const num1 = await fn(1);
  console.log(num1); // 2
  const num2 = await fn(num1);
  console.log(num2); // 4
  const num3 = await fn(num2);
  console.log(num3); // 8
  return num3;
}
asyncFn()

源码来源

@LifeIsTerrible
Copy link

function* generatorFunc() {
   const data1 = yield getData()
   console.log('data1', data1);
   const data2 = yield getDataTwo()
   console.log('data2', data2);
}
// 自动执行 
function autoGenerateFunc(generatorFunc) {
   return function () {
       // 生成迭代器
       const gen = generatorFunc.apply(this, arguments)
       return new Promise((resolve, reject) => {
           const step = (p, arg) => {
               let genObj;
               try {
                   genObj = gen[p](arg)
               } catch (error) {
                   return reject(error)
               }
               const { value, done } = genObj;
               if (done) {
                   return resolve(value)
               } else {
                   return Promise.resolve(value).then(val => step('next', val), err => step('throw', err))
               }
           }
           step('next')
       })
   }
}

@cscty
Copy link

cscty commented Jul 4, 2023

let getData = () => {
let random = Math.random()
return new Promise((resolve, reject) =>
setTimeout(() => {
random > 0.9 ? resolve('成功的数据') : reject('失败的数据')
}, 1000)
)
}
// 实现async 和 await
async function c() {
const data1 = await getData()
console.log(data1, '我是data1')
const data2 = await getData()
console.log(data2, '我是data2')
}
// console.log(c())
function asyncToGenerator(asyncToGenerator) {
let gen = asyncToGenerator()
return new Promise((resolve, reject) => {
function step(key, data) {
let result
try {
result = genkey
// 如果key为throw,并且generator函数没有捕获的话,会直接结束。如果有捕获的话,跳到下一个yield关键处
} catch (error) {
return reject(error)
}
const { done, value } = result
if (done) {
resolve(value)
} else {
Promise.resolve(value).then(
(data) => {
step('next', data)
},
(error) => {
step('throw', error)
}
)
}
}
step('next')
})
}
function* generator() {
try {
const data1 = yield getData()
console.log(data1, '我是data1')
const data2 = yield getData()
console.log(data2, '我是data2')
} catch (error) {}
return '333'
}
console.log(asyncToGenerator(generator))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants