• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >JavaScript > 详解js的异步编程技术的方法

详解js的异步编程技术的方法

作者:大菜鸟231 字体:[增加 减小] 来源:互联网 时间:2017-05-11

大菜鸟231通过本文主要向大家介绍了node.js开发实战详解,js prototype详解,js指标详解附图,js详解,js指标详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

基于浏览器的事件轮询机制(以及Node.js中的事件轮询机制),JavaScript常常会运行在异步环境中。由于JavaScript本身语言的特性(不需要程序员操控线程/进程),在js中解决异步化编程的方法就显得相当重要。可以说一个完整的项目中,js开发人员是不可能不面对异步操作的。本文将详细介绍几种经典JavaScript异步编程串行化方法,同时也将简单介绍一下ES6提供的Promise顺序执行方法。

一.回调函数

(1)经典回调函数方式:嵌套内联函数

假设我们有一个ajax()方法,他接收一个url参数,向该地址发起一个异步请求,在请求结束时执行第二个参数—一个回调函数:

ajax(url,function(result){
 console.log(result);
});
</div>

可以说这种方式几乎是每个前端开发人员都用过的回调函数方式,有了这样的回调机制,开发人员就不用编写类似下面这样的代码来推测服务器请求什么时候返回:

var result=ajax(url);
setTimeout(function(result){
 console.log(result);
},400);
</div>

大家应该能明白我此处想表达的意思。我们设置了一个延迟400毫秒的定时器,来假设我们发出的ajax请求会在400毫秒之内完成。否则,我们将会操作一个undefined的result。

但是有一个问题随着项目的扩大渐渐浮现出来:如果场景需要我们多层嵌套回调函数,代码将变得难以阅读和维护:

ajax(url0,function(result0){
 ajax(result0.url1,function(result1){
  ajax(result1.url2,function(result2){
   console.log(result2);
  });
 });
});
</div>

(2)调用外部函数

为了解决内联回调函数暴露出来的代码混乱问题,我们引入外部函数调用来解决类似问题:

function handle2(result){
 console.log(result);
}
function handle1(result){
 ajax(result.url,function(result){
  handle2(result);
 });
}
ajax(url,function(result){
 handle1(result);
});
</div>

通过这种拆分内联函数,来调用外部函数的优化方法,能极大的保持代码的简洁性。

二.制定回调管理器

观察流行的JavaScript流程控制工具,例如Nimble、Step、Seq,我们会学习到一种简洁的设计模式:通过回调管理器来控制异步JavaScript执行流程,下面是一个典型的回调管理器的关键代码示例:

var Flow={};
//设置next方法,在上一个方法完成时调用下一个方法
Flow.next=function(){
 if(this.stack[0]){
  //弹出方法栈中的第一个方法,并执行他
  this.stack.shift()();
 }
};
//设置series方法,接收一个函数数组,并按序执行
Flow.series=function(arr){
 this.stack=arr;
 this.next();
};

//通过Flow.series我们能够控制传入的函数的执行顺序
Flow.series([
  function(){
   //do something
   console.log(1);
   Flow.next();
  },
  function(next){
   //do something
   console.log(2);
   Flow.next();
  }
]);

</div>

我们初始化了一个Flow控制器,为他设计了series和next两个函数属性。在我们编写的业务方法内部,在方法结尾处通过调用Flow.next()的方式来顺序触发下一个方法;通过执行series方法来顺序执行异步函数。这种通过核心控制器来管理异步函数调用的方式简化了我们的编程过程,让开发人员能够投入更多精力在业务逻辑上。

三.全局标记控制

(1)简单计数器控制

也许上面介绍的异步方法仍然不能满足实际开发中的业务场景:假设我们有a(),b(),c()三个方法,a和b没有依赖关系,可以异步进行。但是c必须在a和b都完成之后才能触发。为满足这样的逻辑实现,我们加入一个全局计数器来控制代码的执行流程:

var flag=2;
var aValue,bValue;
function a(){
 aValue=1;
 flag--;
 c();
}
function b(){
 setTimeout(function(){
  bValue=2;
  flag--;
  c();
 },200);
}
function c(){
 if(flag==0){
  console.log("after a and b:"+(aValue+bValue));
 }
}
a();
b();

</div>

我们设置了一个全局变量flag来监控方法a和方法b的完成情况。方法b通过设置一个200毫秒的定时器来模拟网络环境,最终会在b方法执行完成之后成功调用c方法。这样我们就实现了对方法a(),b(),c()的依赖调用。

(2)面向数据的控制

当上述方案在复杂场景下应用时,会出现如下问题:产品经过多个版本迭代,c方法依赖更多的方法,因此计数器flag需要不断的变化;产品迭代过程中更换了开发人员。当出现上述两种情况时,代码的逻辑将会变得混乱不堪,flag标记符是否能保持简明正确很大程度上受到了产品迭代的影响。因此我们提出面向数据的优化改进。

在真实的开发场景中,存在方法依赖的原因基本都是因为存在数据依赖,对于上面那个简单的示例:c方法依赖于a方法和b方法操作的结果,而不是依赖于flag是否为0。因此我们可以通过检查依赖方法是否已经完成了数据处理来代替检查标记符是否已经被置为0,在这个例子中也就是在c方法中检查aValue和bValue是否已经完成了赋值:

function c(){
 if(aValue!==undefined && bValue!==undefined){
  console.log("after a and b:"+(aValue+bValue));
 }
}

</div>

针对更加通用的场景,我们将上述代码修改为下:

var checkDependency={};
var aValue,bValue;
function a(){
 aValue=1;
 checkDependency.a=true;
 c();
}
function b(){
 setTimeout(function(){
  bValue=2;
  checkDependency.b=true;
  c();
 },200);
}
function c(){
 if(checkDependency.a && checkDependency.b){
  console.log("after a and b:"+(aValue+bValue));
 }
}
a();
b();

</div>

通过面向数据的检查方式,未来扩展时,我们仅需要在新增的方法中增加对checkDependency对象的修改,并且在c方法中检查相应属性的存在就能实现异步依赖方法的顺序执行。

四.ES6新增方法—Promise类

为了解决JavaScript中异步方法的复杂性,官方引入了一种统一的控制方式:

var bool=false;
/*
 * 新建一个Promise实例,向构造函数传入一个异步执行函数
 * 异步函数会接受两个参数,由Promise传入,对应then方法中传入的方法
 */
var promise=new Promise(function(resolve,reject){
 setTimeout(function(){
  if(bool){
   //根据执行情况相应调用resolve和reject
   resolve(bool);
  }else{
   reject(bool);
  }
 },200);
});
//通过then向Promise实例传入解决方法
promise.then(function resolve(result){
 console.log("success");
},function reject(result){
 console.log("failure");
});

</div>

上例代码展示了一个基础的Promise应用,也许实际场景中更加多见的是下面这种链式调用:

new Promise(function(res,rej){
 if(/*异步调用成功*/){
  res(data);
 }else{
  rej(error);
 }
}).then(function resolve(result){
 console.log("success");
},function reject(result){
 console.log("failure");
});

</div>

如果对Promise感兴趣的话,可以在网上寻找资料继续深入学习!

关于Promise的兼容性,通常web前端JavaScript代码中不会直接使用Promise(通过caniuse.com网站查询发现Android4.4不支持Promise)。如果特别想使用的,往往会在项目中附带一些补足兼容性的promise类库;而后端Node.js可以放心使用Promise类来管理异步逻辑。

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

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JS触摸事件、手势事件详解
  • 详解Node.js串行化流程控制
  • 详解node.js平台下Express的session与cookie模块包的配置
  • JS条形码(一维码)插件JsBarcode用法详解【编码类型、参数、属性】
  • JS排序之冒泡排序详解
  • JS排序之快速排序详解
  • JS排序之选择排序详解
  • 详解node.js搭建代理服务器请求数据
  • 详解Node.js实现301、302重定向服务
  • js时间查询插件使用详解

相关文章

  • 2017-05-11解决ajax不能访问本地文件问题(利用js跨域原理)
  • 2017-05-11微信小程序实现图片轮播及文件上传
  • 2017-05-11利用n 升级工具升级Node.js版本及在mac环境下的坑
  • 2017-05-11vue数据双向绑定原理解析(get & set)
  • 2017-05-11jQuery中map函数的两种方式
  • 2017-05-11AngulerJS学习之按需动态加载文件
  • 2017-05-11js实现手机发送验证码功能
  • 2017-05-11jQuery基于正则表达式的表单验证功能示例
  • 2017-05-11使用grunt合并压缩js和css文件的方法
  • 2017-05-11json的结构与遍历方法实例分析

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 超简单的Vue.js环境搭建教程
    • Node.js对MongoDB数据库实现模糊查询的方法
    • openLayer4动态改变标注图标
    • 为JQuery EasyUI 表单组件增加焦点切换功能的方法
    • 使用BootStrap实现标签切换原理解析
    • 原生js实现网页顶部自动下拉/收缩广告效果
    • Vue 短信验证码组件开发详解
    • 值得分享和收藏的xmlplus组件学习教程
    • js实现简单的二级联动效果
    • JavaScript关联数组用法分析【概念、定义、遍历】

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有