javascript异步编程的六种方式总结


Posted in Javascript onMay 17, 2019

异步编程

众所周知 JavaScript 是单线程工作,也就是只有一个脚本执行完成后才能执行下一个脚本,两个脚本不能同时执行,如果某个脚本耗时很长,后面的脚本都必须排队等着,会拖延整个程序的执行。那么如何让程序像人类一样可以多线程工作呢?以下为几种异步编程方式的总结,希望与君共勉。

  1. 回调函数
  2. 事件监听
  3. 发布订阅模式
  4. Promise
  5. Generator (ES6)
  6. async (ES7)

异步编程传统的解决方案:回调函数和事件监听

初始示例:假设有两个函数, f1 和 f2,f1 是一个需要一定时间的函数。

function f1() {
  setTimeout(function(){
    console.log('先执行 f1')
  },1000)
}
function f2() {
  console.log('再执行 f2')
}

回调函数

因为 f1 是一个需要一定时间的函数,所以可以将 f2 写成 f1 的回调函数,将同步操作变成异步操作,f1 不会阻塞程序的运行,f2 也无需空空等待,例如 JQuery 的 ajax。

回调函数的demo:

function f1(f2){
  setTimeout(function(){
    console.log('先执行 f1')
  },1000)
  f2()
}
function f2() {
  console.log('再执行 f2')
}

效果如下:

 javascript异步编程的六种方式总结

总结:回调函数易于实现、便于理解,但是多次回调会导致代码高度耦合

事件监听

脚本的执行不取决代码的顺序,而取决于某一个事件是否发生。

事件监听的demo

$(document).ready(function(){
   console.log('DOM 已经 ready')
});

发布订阅模式

发布/订阅模式是利用一个消息中心,发布者发布一个消息给消息中心,订阅者从消息中心订阅该消息,。类似于 vue 的父子组件之间的传值。

发布订阅模式的 demo

//订阅done事件
$('#app').on('done',function(data){
  console.log(data)
})
//发布事件
$('#app').trigger('done,'haha')

Promise

Promise 实际就是一个对象, 从它可以获得异步操作的消息,Promise 对象有三种状态,pending(进行中)、fulfilled(已成功)和rejected(已失败)。Promise 的状态一旦改变之后,就不会在发生任何变化,将回调函数变成了链式调用。

Promise 封装异步请求demo

export default function getMethods (url){
  return new Promise(function(resolve, reject){
    axios.get(url).then(res => {
      resolve(res)
    }).catch(err =>{
      reject(err)
    })
  })
}

getMethods('/api/xxx').then(res => {
  console.log(res)
}, err => {
  console.log(err)
})

Generator

Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,使用该对象的 next() 方法,可以遍历 Generator 函数内部的每一个状态,直到 return 语句。

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式, yield是暂停执行的标记。

next() 方法遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

Generator 的 demo

function *generatorDemo() {
 yield 'hello';
 yield 1 + 2;
 return 'ok';
}

var demo = generatorDemo()

demo.next()  // { value: 'hello', done: false } 
demo.next()  // { value: 3, done: false } 
demo.next()  // { value: 'ok', done: ture } 
demo.next()  // { value: undefined, done: ture }

async

async函数返回的是一个 Promise 对象,可以使用 then 方法添加回调函数,async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

1.await命令后面返回的是 Promise 对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。

async 的 demo1

async function demo() {
 try {
  await new Promise(function (resolve, reject) {
   // something
  });
 } catch (err) {
  console.log(err);
 }
}

demo().then(data => {
  console.log(data) // 
})

参考文献

https://developers.google.com/web/fundamentals/primers/promises
http://es6.ruanyifeng.com

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
简单的jquery拖拽排序效果实现代码
Sep 20 Javascript
js实现的仿新浪微博完美的时间组件升级版
Dec 20 Javascript
探讨js中的双感叹号判断
Nov 11 Javascript
Javascript中Array用法实例分析
Jun 13 Javascript
JavaScript淡入淡出渐变简单实例
Aug 06 Javascript
AngularJs表单校验功能实例代码
Feb 09 Javascript
js实现旋转木马效果
Mar 17 Javascript
JavaScript登录记住密码操作(超简单代码)
Mar 22 Javascript
bootstrap可编辑下拉框jquery.editable-select
Oct 12 jQuery
vue中使用vue-router切换页面时滚动条自动滚动到顶部的方法
Nov 28 Javascript
关于node-bindings无法在Electron中使用的解决办法
Dec 18 Javascript
JS如何在不同平台实现多语言方式
Jul 16 Javascript
150行代码带你实现微信小程序中的数据侦听
May 17 #Javascript
angular4应用中输入的最小值和最大值的方法
May 17 #Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
May 17 #jQuery
详解 微信小程序开发框架(MINA)
May 17 #Javascript
Vue模板语法中数据绑定的实例代码
May 17 #Javascript
jQuery控制input只能输入数字和两位小数的方法
May 16 #jQuery
微信小程序云开发详细教程
May 16 #Javascript
You might like
xml 与javascript结合的问题解决方法
2007/03/24 Javascript
javascript 冒号 使用说明
2009/06/06 Javascript
javascript 框架小结 个人工作经验
2009/06/13 Javascript
jquery 简单导航实现代码
2009/09/11 Javascript
Javascript单元测试框架QUnitjs详细介绍
2014/05/08 Javascript
通过js来制作复选框的全选和不选效果
2014/05/22 Javascript
基于NodeJS的前后端分离的思考与实践(六)Nginx + Node.js + Java 的软件栈部署实践
2014/09/26 NodeJs
在HTML代码中使用JavaScript代码的例子
2014/10/16 Javascript
JavaScript设计模式之工厂方法模式介绍
2014/12/28 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
js提示框替代系统alert,自动关闭alert对话框的实现方法
2016/11/07 Javascript
Vue2.0实现1.0的搜索过滤器功能实例代码
2017/03/20 Javascript
微信小程序 循环及嵌套循环的使用总结
2017/09/26 Javascript
vue中配置mint-ui报css错误问题的解决方法
2017/10/11 Javascript
基于js中style.width与offsetWidth的区别(详解)
2017/11/12 Javascript
微信小程序异步API为Promise简化异步编程的操作方法
2018/08/14 Javascript
小程序兼容安卓和IOS数据处理问题及坑
2018/09/18 Javascript
一篇文章带你浅入webpack的DLL优化打包
2020/02/20 Javascript
[07:06]2018DOTA2国际邀请赛寻真——卫冕冠军Team Liquid
2018/08/10 DOTA
python socket 超时设置 errno 10054
2014/07/01 Python
wxPython框架类和面板类的使用实例
2014/09/28 Python
九步学会Python装饰器
2015/05/09 Python
python中文件变化监控示例(watchdog)
2017/10/16 Python
使用Python的package机制如何简化utils包设计详解
2017/12/11 Python
python 读取修改pcap包的例子
2019/07/23 Python
Windows平台Python编程必会模块之pywin32介绍
2019/10/01 Python
python中删除某个元素的方法解析
2019/11/05 Python
python 读取yaml文件的两种方法(在unittest中使用)
2020/12/01 Python
法国二手手袋、手表和奢侈珠宝购物网站:Collector Square
2018/07/05 全球购物
数据库什么时候应该被重组
2012/11/02 面试题
介绍一下Linux中的链接
2016/06/05 面试题
Java中的基本数据类型所占存储空间大小固定的吗
2012/02/15 面试题
餐饮主管岗位职责
2013/12/10 职场文书
培训专员岗位职责
2014/02/26 职场文书
社会心理学学习心得体会
2016/01/22 职场文书
CSS中实现动画效果-附案例
2022/02/28 HTML / CSS