0

0

详解JavaScript异步编程技术

黄舟

黄舟

发布时间:2017-02-27 14:23:41

|

1451人浏览过

|

来源于php中文网

原创

详解JavaScript异步编程技术

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

一.回调函数

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

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

ajax(url,function(result){
    console.log(result);
});

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

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

大家应该能明白我此处想表达的意思。我们设置了一个延迟400毫秒的定时器,来假设我们发出的ajax请求会在400毫秒之内完成。否则,我们将会操作一个undefinedresult
但是有一个问题随着项目的扩大渐渐浮现出来:如果场景需要我们多层嵌套回调函数,代码将变得难以阅读和维护:

立即学习Java免费学习笔记(深入)”;

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

(2)调用外部函数

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

function handle2(result){
    console.log(result);
}function handle1(result){
    ajax(result.url,function(result){
        handle2(result);
    });
}
ajax(url,function(result){
    handle1(result);
});

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

二.制定回调管理器

观察流行的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();
        }
]);

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

三.全局标记控制

(1)简单计数器控制

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

《PHP程序设计》第二版
《PHP程序设计》第二版

本书图文并茂,详细讲解了使用LAMP(PHP)脚本语言开发动态Web程序的方法,如架设WAMP平台,安装与配置开源Moodle平台,PHP程序设计技术,开发用户注册与验证模块,架设LAMP平台。 本书适合计算机及其相关专业本、专科学生作为学习LAMP(PHP)程序设计或动态Web编程的教材使用,也适合对动态Web编程感兴趣的读者自觉使用,对LAMP(PHP)程序设计人员也具有一定的参考价值。

下载
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();

我们设置了一个全局变量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));
    }
}

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

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();

通过面向数据的检查方式,未来扩展时,我们仅需要在新增的方法中增加对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");
});

上例代码展示了一个基础的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");
});

如果对Promise感兴趣的话,可以在网上寻找资料继续深入学习!
关于Promise的兼容性,通常web前端JavaScript代码中不会直接使用Promise(通过caniuse.com网站查询发现Android4.4不支持Promise)。如果特别想使用的,往往会在项目中附带一些补足兼容性的promise类库;而后端Node.js可以放心使用Promise类来管理异步逻辑。
这里写图片描述

 以上就是详解JavaScript异步编程技术的内容,更多相关内容请关注PHP中文网(www.php.cn)!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

19

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

13

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

8

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

567

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

209

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

346

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

11

2026.01.28

php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

16

2026.01.28

Java 消息队列与异步架构实战
Java 消息队列与异步架构实战

本专题系统讲解 Java 在消息队列与异步系统架构中的核心应用,涵盖消息队列基本原理、Kafka 与 RabbitMQ 的使用场景对比、生产者与消费者模型、消息可靠性与顺序性保障、重复消费与幂等处理,以及在高并发系统中的异步解耦设计。通过实战案例,帮助学习者掌握 使用 Java 构建高吞吐、高可靠异步消息系统的完整思路。

11

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号