前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS异步编程的一些总结

JS异步编程的一些总结

作者头像
terrence386
发布2022-07-14 21:10:54
4100
发布2022-07-14 21:10:54
举报
文章被收录于专栏:JavaScript高级程序设计

个人公众号不知道从什么时候开始不支持个人认证了,所以有些权限个人无法使用,比如微信网页开发,因为根本没有网页授权域名,即使配置了js安全接口域名,个人仍然无法进行微信网页开发。

前情回顾

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

JS中的异步编程

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

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

代码语言:javascript
复制
function initPage(){
  console.log("page-inited")
  showMap()
}
function showMap(){
  console.log('map-stand-by')
}
//
initPage()

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

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

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

代码语言:javascript
复制
  loginModule.success(function(res){
    navModule.setAvatar(res.avatar)
    selfCenterModule.setInfo(res)
  })

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

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

代码语言:javascript
复制
// 导航
let navModule = (function(){
  loginModule.listen('succ',function(res){
    navModule.setAvatar(res.avatar)
  })
// 个人中心
let selfCenterModule = (function(){
  selfCenterModule.listen('succ',function(res){
    selfCenterModule.setInfo(res.avatar)
  })
})()

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

代码语言:javascript
复制
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关键字。对它有兴趣的可以去看下迭代器生成器的知识点。

题外话

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

javascript基础知识总结

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JavaScript高级程序设计 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前情回顾
  • JS中的异步编程
  • 题外话
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档