来聊聊前端的异步

本文详细介绍了前端异步编程的原理与实践,从出现原因、使用场景到实现方式,包括回调函数、事件监听、发布/订阅模式以及Promise和async/await的优缺点与使用场景。还探讨了Ajax、自定义弹窗处理和图片加载等应用场景,以及如何通过Generator和async/await解决回调地狱问题。
摘要由CSDN通过智能技术生成

异步

出现的原因

JavaScript语言的执行环境是"单线程"
所谓"单线程",就是指一次只能只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
单线程这种模式好处是实现起来比较简单,执行环境单一。坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段JavaScript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。
为了解决这个问题,JavaScript语言将任务的执行模式分成两种,同步和异步。

异步的使用场景

Ajax操作

异步编程的实现

回调函数

优点:简单丶很容易理解和部署。
缺点:不利于阅读和维护,各部分之间高度耦合,流程会很混乱,而且每个任务只能指定一个回调函数。
代码实现// 假如有两个函数f1和f2 后者等待前者的执行结果
// 如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数

function f2© {
console.log(c, ‘hehe’);
}
function f1(callback) {
setTimeout(function() {
// f1任务代码
console.log(‘f1执行完’);
callback(‘f2开始执行’, ‘hehe’);
}, 1000);
}
f1(f2);
复制代码

事件监听

代码实现
优点:比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合",有利于实现模块化。
缺点:整个程序都变成事件驱动,运行流程会变得很不流畅。f1.on(‘done’, f2);
复制代码

发布/订阅

定义:我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"一个信号,其他任务可以向信号中心"订阅"整个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式",又称"观察者模式"。
优点:

这种方法的性质和"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号丶每个信号有多少订阅者,从而监控程序的运行。
一是时间上的解耦,而是对象上的解耦
即可用于异步编程中,也可以用帮助我们完成更松耦合的代码编写

缺点:

创建订阅者本身需要消耗一定的时间和内存
当订阅一个消息时,也许次消息并没有发生,但这个订阅者会始终存在内存中
观察者模式弱化了对象之间的联系,这本是好事,但如果过度使用,对象与对象之间的联系也会隐藏的很深,会导致项目的难以追踪维护和理解。

使用场景

DOM事件
自定义事件

代码实现function Event() {
// 存储不同的事件类型对应不同的处理函数,保证后续emmit可以执行。
this.cache = {};
}
// 绑定事件
Event.prototype.on = function(type, handle) {
if(!this.cache[type]) {
this.cache[type] = [handle];
}else {
this.cache[type].push(handle);
}
}
// 事件触发
Event.prototype.emmit = function() {
var type = arguments[0],
arg = [].slice.call(arguments, 1);
for(var i = 0; i < this.cache[type].length; i++) {
this.cache[type][i].apply(this, arg);
if(this.cache[type][i].flag) {
this.cache[type].splice(i, 1);
if(this.cache[type][i].flag) {
this.cache[type].splice(i, 1);
}
}
}
}
// 解除某个事件类型
Event.prototype.empty = function(type) {
this.cache[type] = [];
}
// 解除某个事件
Event.prototype.remove = function(type, handle) {
this.cache[type] = this.cache[type].filter((ele) => ele != handle);
}
// 绑定一次事件
Event.prototype.once = function(type, handle) {
if(!this.cache[type]) {
this.cache[type] = [];
}
// 做标记
handle.flag = true;
this.cache[type].push(handle);
}

function detail1(time) {
console.log(‘overtime1’ + time);
}
function detail2(time) {
console.log(‘overtime2’ + time);
}
var oE = new Event();
oE.on(‘over’, detail1);
oE.on(‘over’, detail2);
oE.emmit(‘over’, ‘2019-11-11’);
oE.remove(‘over’, detail2);
oE.emmit(‘over’, ‘second-11-11’);
复制代码

Promise对象

定义

是CommonJS工作组提出的一种规范,目的是为了异步编程提供统一接口。
简单来说,它的思想就是,每一个异步任务都返回一个Promise对象,该对象有一个then方法,允许指定回调函数。

优点:

回调函数变成链式写法,程序的流程可以看得很清楚,而且有一整套流程的配套方法。
而且,它还有一个前面三种方法都没有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值