手写async&await

这个很好用,我们要写一个类似的方法,asyncFunction,至于await完全是添头。

Promise和generator方法

经常有人说其实async就是generator的语法糖,也用来弥补它的一些不足之处,所以来尝试下,如何使用generator实现async,看看原理 ​ 我们先写一个简单的promise生成器作为异步函数

javascript 复制代码
const delayer = t => new Promise(resolve => setTimeout(resolve, t))

我们来看看如果使用async,怎么转换为同步

javascript 复制代码
async function count(){
  await delayer(1000);
  console.log(1);
  await delayer(1000);
  console.log(1);
  await delayer(1000);
  console.log(1);
}
// 执行count的结果是每隔一秒打印一个1

关于generator的一些方法和使用这边就不做过多介绍了,想要看的同学可以找度娘或者点击文章下方的参考文档。 接下来就是开始实现的阶段了,其实我们要做的是把generator从手动执行变成自动执行,也就是自动next到底,获得预期的返回。 我们先定义一个generator函数

javascript 复制代码
function* genFunction(){
  console.log(2);
	const d1 = yield delayer(1000);
  console.log(22);
  const d2 = yield delayer(1000);
  console.log(222);
  const d3 = yield delayer(1000);
  console.log(2222);
  return 'result'
}

接下来就是自动化函数执行阶段了

javascript 复制代码
function asynction(genFunction, ...args){
  const genFun = genFunction(...args)
  // 设置执行函数
  function next(data) {
    return new Promise((resolve, reject) => {
     const {value, result} = genFun.next(data)
     if (done) return
     value.then(data => next(data)).catch(e => reject(e))  
    })
  }
  return next()
}

这个方案看起来不是那么正常,看下一个

其他方案

其实差不多

typescript 复制代码
// 现在有一个方法
var a = 1;
const delay = () => {
  return new Promise((resv) => setTimeout(() => resv(a++), 1000));
};
const fn = () => {
  console.log("1");
  delay();
  console.log("2");
  delay();
  console.log("3");
  delay();
};
// 看得出是异步的,可能会同时输出1,我们想让他们变同步
// 使用sync来执行
const fn1 = async () => {
  console.log("1");
  await delay();
  console.log("2");
  await delay();
  console.log("3");
  await delay();
};
// 自己搞一个async实现这个东西,首先使用generator试试
function* fn2(cc) {
  console.log("1");
  yield delay();
  console.log("2");
  yield delay();
  console.log("3");
  yield delay();
  return 555;
}
// 如果做个自动化next,也就完成了await的作用了,那么需要的是什么,是回调!
// 一直执行,直到next的done = true
function run(gFun, ...initValues) {
  let gen = gFun(...initValues);
  function next() {
    return new Promise((resolve, reject) => {
      let result = gen.next();
      if (result.done) return;
      result.value.then(() => next()).catch((e) => reject(e));
    });
  }
  return next();
}

// run(fn2).catch((err) => console.log(err));

function run2(gFun, ...initValues) {
  let gen = gFun(...initValues);
  return new Promise((res, rej) => {
    let result;
    const next = (...args) => {
      console.log("args", args);
      result = gen.next(...args);
      if (result.done) {
        console.log("xxx", result.value);
        return res(result.value);
      }
      return result.value.then((res) => {
        console.log("yyy", result.value, res);
        return next(222);
      });
    };
    return next(2);
  });
}
async function kk() {
  console.log(await run2(fn2));
}
kk();

​ 参考:手写async/await 手写async await的最简实现(20行搞定)!阿里字节面试必考

相关推荐
XinZong7 分钟前
【VSCode插件推荐】想准时下班,你需要codemoss的帮助,分享AI写代码的愉快体验,附详细安装教程
前端·程序员
ErvinHowell14 分钟前
文件MD5生成性能大提升!如何实现分片与Worker优化
前端·vue.js·算法
想做白天梦31 分钟前
LeetCode :150. 逆波兰表达式求值(含求后缀表达式和中缀转后缀表达式)
java·前端·算法
s甜甜的学习之旅1 小时前
前端js处理list(数组)
开发语言·前端·javascript
小布布的不1 小时前
MyBatis 返回 Map 或 List<Map>时,时间类型数据,默认为LocalDateTime,响应给前端默认含有‘T‘字符
前端·mybatis·springboot
aPurpleBerry1 小时前
Vue3+axios+Vite配置Proxy代理解决跨域
前端·javascript·vue.js
JustCouvrir2 小时前
macOS|前端工程部署到Nginx服务器
服务器·前端·nginx
代码哈士奇2 小时前
mqtt 传递和推送 温湿度计消息 js
开发语言·前端·javascript·硬件·esp8266
jokerest1232 小时前
web——[GXYCTF2019]Ping Ping Ping1——过滤和绕过
前端
GISer_Jing2 小时前
[前端项目Overview]表单构建器vue-form-generator
前端·javascript·vue.js