更多课程 选择中心


Web培训

400-996-5531

Web培训

总结5种JavaScript异步解决方案


1、回调

回调简单地理解为一个函数作为参数传递给另一个函数,回调是早期最常用的异步解决方案之一。

回调不一定是异步的,也不直接相关。

举个简单的例子:

functionf1(cb){

setTimeout(()=>;

{

cb&;&;cb();

},

2000);

}

f1(()=>;

{console.log("1");

});

如上,我们在函数f1中使用setTimeout模拟一个耗时2s的任务,在耗时任务结束时抛出回调,这样我们就可以调用它,让回调函数在耗时结束时执行函数f1中的任务。

这样,我们就把同步操作变成了异步操作。f1不会阻塞程序,相当于先执行程序的主要逻辑,推迟执行耗时操作。

回调的优点和缺点

优点:简单,容易理解。

缺点:代码不优雅,可读性差,不易维护,耦合度高,层层嵌套造成回调地狱。

2、事件监听(发布订阅模式)

发布-订阅模式定义了对象之间一对多的依赖关系,这样当一个对象的状态发生变化时,所有依赖它的对象都会得到通知。

我们都使用过发布-订阅模式,例如,如果我们将事件函数绑定到DOM节点。

document.body.addEventListener('click',function(){

console.log('click');

})

但这只是发布-订阅模式最简单的使用,在很多场景下我们往往会使用一些自定义事件来满足我们的需求。

有很多方法可以实现发布-订阅模式,所以这里有一个使用类的简单实现。

classEmitter{constructor(){

//_listenerarray,keyisthecustomeventname,valueistheexecutioncallbackarray-astheremaybemorethanonethis._listener=[]}//订阅监听事件on(type,fn){

//Determineiftheeventexistsinthe_listenerarray.//Existstopushthecallbacktothevaluearraycorrespondingtotheeventname,doesnotexisttoadddirectlythis._listener[type]?this._listener[type].push(fn):(this._listener[type]=[fn])}

//PublishTriggerEventtrigger(type,...rest){

//Determineifthetriggereventexistsif(!this._listener[type])return

//Iteratethroughthearrayofcallbacksexecutingtheeventandpasstheparametersthis._listener[type].forEach(callback=>;callback(...rest))

}

}

如上所示,我们创建了一个Emitter类,并在和触发器上添加了两个原型方法,使用如下。

//Createanemitterinstanceconstemitter=newEmitter()emitter.on("done",function(arg1,arg2){

console.log(arg1,arg2)

})

emitter.on("done",function(arg1,arg2){

console.log(arg2,arg1)

})

functionfn1(){console.log('Iamthemainprogram')setTimeout(()=>;

{

emitter.trigger("done","AsynchronousparameterI","AsynchronousparameterII")},1000)}

fn1()

我们先创建一个emitter实例,然后注册事件,然后触发事件,这样也解决了异步问题。

事件监听的优点和缺点

优点:更符合模块化思想,我们在编写自己的监听器的时候可以做很多优化,从而更好的监听程序的运行。

缺点:整个程序变成了事件驱动,或多或少影响了流程,而且每次使用都要注册事件监听器然后触发,比较麻烦,代码也不是很优雅。

3、Promise

ES6标准化并引入了Promise对象,这是一种异步编程的解决方案。

简单的说,就是用同步的方式写异步代码,可以用来解决回调地狱问题。

Promise对象的状态一旦改变,就不会再改变,只有两种可能的改变。

1)由待定改为已解决。

2)由Pending改为Rejected。

我们使用setTimeout来模拟异步操作。

functionanalogAsync(n){

returnnewPromise((resolve)=>;

{setTimeout(()=>;resolve(n+500),n);

});

}functionfn1(n){

console.log(`step1with${n}`);

returnanalogAsync(n);

}functionfn2(n){

console.log(`step2with${n}`);

returnanalogAsync(n);

}functionfn3(n){

console.log(`step3with${n}`);

returnanalogAsync(n);

}

使用Promise来实现。

functionfn(){

lettime1=0;

fn1(time1).then((time2)=>;

fn2(time2)).then((time3)=>;

fn3(time3)).then((res)=>;

{

console.log(`resultis${res}`);

});}

fn(

);

Promise优点和缺点

优点:Promise以同步的方式编写异步代码,避免了回调函数层层嵌套,可读性更强。链式操作,可以在then中继续写Promise对象并return,然后继续调用then进行回调操作。

缺点:Promise对象一旦创建就会立即执行,不能中途取消。如果没有设置回调函数,Promise会在内部抛出错误,不会向外流。

4、Generator

Generator其实就是一个函数,只不过是一个特殊的函数。Generator的特别之处在于它可以中途停止。

function*generatorFn(){

console.log("a");

yield'1';console.log("b");

yield'2';console.log("c");

return'3';

}

letit=generatorFn();

it.next();

it.next();

it.next();

it.next();

上面的示例是一个具有以下特征的生成器函数。与普通函数不同,Generator函数在函数之后和函数名称之前有一个*,该函数有一个内部yield字段,函数调用后的返回值使用next方法。

Generator的优点和缺点

优点:优雅的流程控制方法,允许函数被中断地执行。

缺点:Generator函数的执行必须依赖executor,对于只做异步处理还是不太方便。

5、async/await

ES2017标准引入了async函数,使得异步操作更加方便。async是异步的意思,await是asyncwait的简写,也就是异步等待。async/await被许多人认为是js中异步操作的终极和最优雅的解决方案。

异步在做什么?

async函数返回一个Promise对象。如果直接在async函数中返回一个直接量,async会通过Promise.resolve()将直接量包装在一个Promise对象中。

await是什么?

await是一个表达式,其计算结果为Promise对象或其他值(换句话说,没有特殊限定,无论如何)。

如果await后面没有跟Promise对象,则直接执行。

如果await后面跟着一个Promise对象,它会阻塞后面的代码,Promise对象解析,然后获取resolve的值作为await表达式的结果。

await只能在异步函数中使用

上面使用setTimeout来模拟异步操作,我们使用async/await来实现。

asyncfunctionfn(){

lettime1=0;

lettime2=awaitfn1(time1);

lettime3=awaitfn2(time2);

letres=awaitfn3(time3);

console.log(`resultis${res}`);

}

fn();

输出结果和上面的Promise实现是一样的,但是async/await的代码结构看起来更清晰,几乎和同步写法一样优雅。

async/await的优点和缺点

优点:内置执行器,语义更好,适用性更广。

缺点:误用await可能会导致性能问题,因为await会阻塞代码。

预约申请免费试听课

填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:2022年Web前端学习路线
下一篇:Web前端工程师需要掌握的技术

前端样式框架用什么技术?

5种流行的前端设计技术是什么?

Web前端开发需要掌握什么?

Web前端好学吗需要天赋吗?

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

贵州省

云南省

广西省

海南省