Sunny-117/js-challenges

await async 如何实现

lxy-Jason opened this issue · 2 comments

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()

源码来源

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 commented

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))