JS异步编程的一些总结

Posted JavaScript高级程序设计

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS异步编程的一些总结相关的知识,希望对你有一定的参考价值。

前情回顾

上篇文章主要分享了事件循环的问题,包括Node的事件循环和JS的事件循环。它们有很多相似之处。今天要聊的是日常中的异步编程实现方案。

JS中的异步编程

我们都知道JS是单线程的,一条任务执行完成之后才会执行下一条任务。这种模式存在两个问题,一是整体花费时间是所有任务的总和。而是一旦某段代码出现错误流程就会被阻塞。如果界面的渲染依赖这段代码,反应到浏览器上就会影响界面的渲染流程,进而出现各种问题。

JS中最常见的解决这个问题的方法有这么几种:一是回调函数。这里其实有一个问题,如何理解回调函数的异步执行??。相信大家都写过这种代码:

function initPage(){
  console.log("page-inited")
  showMap()
}
function showMap(){
  console.log('map-stand-by')
}
//
initPage()

这段代码毫无疑问是同步的,因为showMap()要在initPage()执行完成后才执行。回调函数则不同,回调函数其实是个高阶函数,将函数作为参数传给另外一个函数,这样一来,整个过程不用阻塞,直接允许后续操作。

回调函数的主要问题是,假如后续操作有很多,则需要连续嵌套多层回调函数,即常说的回调地狱

第二种方式是发布-订阅模式。发布订阅可以理解为一种消息通知机制。假如我们需要开发一套商城,必然有多个模块儿,登录,导航个人中心等等。假如导航模块儿依赖登录模块儿,我们的代码有可能是这样的:

  loginModule.success(function(res){
    navModule.setAvatar(res.avatar)
    selfCenterModule.setInfo(res)
  })

假如后期我们又新增加了N多模块,那么我们必然会在loginModule的回调里添加更多的方法去设置对应模块儿的信息。

使用发布订阅以后,可以将这些模块儿解耦出来,不同的模块儿只需要订阅登录成功的消息事件即可。

// 导航
let navModule = (function(){
  loginModule.listen('succ',function(res){
    navModule.setAvatar(res.avatar)
  })
// 个人中心
let selfCenterModule = (function(){
  selfCenterModule.listen('succ',function(res){
    selfCenterModule.setInfo(res.avatar)
  })
})()

发布定阅的实现原理也非常简单:将订阅消息的回调函数放入一个数组缓存中,当触发这个消息时,从数组中取出对应的函数进行执行。

var Event = {
    // 缓存列表
    clientList:[],
    listen:function(fn){
        this.clientList.push(fn)
    },
    trigger:function(){
        let self = this
        // 遍历缓存列表
        for(var i = 0;i<self.clientList.length;i++){
            self.clientList[i]()
        }
    }
}

vuex,redux中都有使用。

第三种是Promise。Promise在目前的开发中应该是使用最多的。它遵循PromiseA+规范。对于Promise本人理解的不够深刻,需要单独思考然后在做总结。

第四种是asyncawait。这两个小东西被称作是异步编程的终极神器。asyncawait关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。因为,在promise语句中,我们只有在then()方法的回调中才可以取到返回值。但是使用await后,我们可以直接取到返回值。这个问题理论上应该和生成器有关。

需要注意的是await关键字只在async函数内有效。如果你在async函数体之外使用它,就会抛出语法错误 SyntaxError

最后一个我能想到的跟异步有关的方法是yieldyield 关键字用来暂停和恢复一个生成器函数。好像这个方法之前也有很多人用。

yield关键字使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。对它有兴趣的可以去看下迭代器生成器的知识点。

题外话

今天在思考一个问题,雍正王朝里,众皇子在争夺皇位的时候。邬思道对雍正说:“争是不争,不争是争。”表面上是劝他不要争,本质上还是告诉他要去争。只是做事都讲求方法罢了。

最后说两句

  1. 动一动您发财的小手, 「点个赞吧」
  2. 动一动您发财的小手, 「点个在看」
  3. 都看到这里了,不妨   「加个关注」
  4. 不妨   「转发一下」,好东西要记得分享
javascript基础知识总结


以上是关于JS异步编程的一些总结的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——JS中的面向对象编程

VSCode自定义代码片段9——JS中的面向对象编程

js学习总结----ajax中的http请求方式及同步编程和异步编程

JavaScript异步编程

20个简洁的 JS 代码片段

在Nuxt.js组件中获取异步数据