前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >每天3分钟,重学ES6-ES12(十五)异步代码处理方案

每天3分钟,重学ES6-ES12(十五)异步代码处理方案

作者头像
虎妞先生
发布2022-09-19 14:19:26
3850
发布2022-09-19 14:19:26
举报
文章被收录于专栏:前端开疆扩土之路

theme: juejin

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

每天3分钟,重学ES6-ES12文章汇总

前言

今天开始和大家一起系统的学习ES6+,每天3分钟,用一把斗地主的时间,重学ES6+,前面我们介绍了promise,生成器和迭代器,async await,现在我们总结一下针对异步代码处理方案

业务场景

请求一个接口,拿到返回值,对返回值进行处理,当作第二个接口的请求参数,拿到返回值处理,当作第三个接口的请求参数。最终数据需要调用依次调用3个接口才能拿到。

1> url: why -> res: why

2> url: res + "aaa" -> res: whyaaa

3> url: res + "bbb" => res: whyaaabbb

代码语言:javascript
复制
function requestData(url) {
// 异步请求的代码会被放入到executor中
return new Promise((resolve, reject) => {
  // 模拟网络请求
  setTimeout(() => {
    // 拿到请求的结果
    resolve(url)
  }, 2000);
})
}

方案一 回调函数

优点:便于理解 缺点:回调地狱,不能捕获错误

代码语言:javascript
复制
ajax('url', () => {
    // callback 函数体
    ajax('url', () => {
        // callback 函数体
        ajax('url', () => {
            // callback 函数体
        })
    })
})

方案二 事件监听

代码语言:javascript
复制
f1.on('done', f2); 
function f1(){     
     setTimeout(function () {       
     // f1的任务代码      
     f1.trigger('done');     
     }, 1000);   
}

优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数;

缺点:整个流程都要变成事件驱动型,运行流程会变得不清晰。

方案三 发布订阅模式

代码语言:javascript
复制
jQuery.subscribe("done", f2);
function f1(){
    setTimeout(function () {
      // f1的任务代码
      jQuery.publish("done");
    }, 1000);
}
jQuery.unsubscribe("done", f2);

与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。

方案四 Promise中then的返回值来解决回调问题

代码语言:javascript
复制
requestData("why").then(res => {
   return requestData(res + "aaa")
}).then(res => {
   return requestData(res + "bbb")
}).then(res => {
   console.log(res)
})

优点:解决了层层回调问题,相对直观 缺点:无法精确捕获到哪个promise错误,链式调用依然不如同步函数代码直观

方案五 Promise + generator实现

代码语言:javascript
复制
function* getData() {
  const res1 = yield requestData("why")
  const res2 = yield requestData(res1 + "aaa")
  const res3 = yield requestData(res2 + "bbb")
  const res4 = yield requestData(res3 + "ccc")
  console.log(res4)
}

// 1> 手动执行生成器函数
const generator = getData()
generator.next().value.then(res => {
  generator.next(res).value.then(res => {
    generator.next(res).value.then(res => {
      generator.next(res)
    })
  })
})

// 2> 自己封装了一个自动执行的函数
function execGenerator(genFn) {
  const generator = genFn()
  function exec(res) {
    const result = generator.next(res)
    if (result.done) {
       return result.value
    }
    result.value.then(res => {
       exec(res)
    })
   }
   exec()
execGenerator(getData)

优点:代码直观,* yield 可以重新组织代码,同步的方式执行异步代码

缺点:无法执行并发请求,只能调用next()一步一步请求,* yield 对开发者不太友好,难以理解

方案六 async/await

代码语言:javascript
复制
async function getData() {
  const res1 = await requestData("why")
  const res2 = await requestData(res1 + "aaa")
  const res3 = await requestData(res2 + "bbb")
  const res4 = await requestData(res3 + "ccc")
  console.log(res4)
}

getData()

async 是generator的语法糖 内置执行器,无需手动执行next()方法

*/yield => async/await

优点:在generator 的基础上更加语义化,使用简单,无需执行next 方法 缺点:无法执行并发请求,必须有try catch才能捕获到异常

业务使用

Promise + async/await

async/await是基于generator的语法糖,返回的也是一个promise,所以返回值可以调用promise的方法。 当处理并发一般Promise.all + async/awit 结合使用

代码语言:javascript
复制
async function getData(){
    await Promise.all([requestData(a),requestData(b)])
}

总结

async await意义在于‘期望异步代码和同步代码可以流畅混淆而不至于被 then 分割’。同步代码不多的情况,async await和promise的使用可以取决于个人喜好。

async/await设计初衷并不是为了取代Promise,而是为了让使用Promise更加方便。

JS异步的发展历程是callback->promise/generator->async/await

这三种历程我认为并没有 相互优越的区别,而是有使用场景的区别

注册事件必须是用回调,async await 可以梳理平常的业务代码 更容易理解拆分业务 ,而generator 适用于需要暂停的业务逻辑,promise 适用于 构建通用异步函数

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • theme: juejin
  • 前言
  • 业务场景
  • 方案一 回调函数
  • 方案二 事件监听
  • 方案三 发布订阅模式
  • 方案四 Promise中then的返回值来解决回调问题
  • 方案五 Promise + generator实现
  • 方案六 async/await
  • 业务使用
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档