手把手教你学前端:总结5种JavaScript异步解决方案

2023-05-28 0 849

1.反弹

反弹单纯地认知为两个表达式做为HTA给另两个表达式,反弹是晚期最常见的触发器软件系统众所周知。

反弹不一定是触发器的,也不间接有关。

举个单纯的范例:

function f1(cb) { setTimeout(() => { cb && cb(); }, 2000);}f1(() => { console.log(“1”);});

如上,他们在表达式f1中采用setTimeout演示两个费时2s的各项任务,在费时各项任务完结时放出反弹,这种他们就能初始化它,让反弹表达式在费时完结时继续执行表达式 f1 中的各项任务。

这种,他们就把同步操作方式变为了触发器操作方式。f1不能堵塞流程,相等于先继续处理流程的主要就方式论,延后继续执行费时操作方式。

反弹的优点和缺点

缺点:单纯,难认知。

缺点:标识符不典雅,时效性差,难于保护,耦合度高,一层层冗余导致反弹冥界。

2.该事件窃听(正式发布订户商业模式)

正式发布-订户商业模式定义了第一类间两对多的倚赖亲密关系,这种当两个第一类的状况发生变化时,大部份倚赖它的第一类单厢获得通告。

他们都采用过正式发布-订户商业模式,比如,假如他们将该事件表达式存取到 DOM 结点。

document.body.addEventListener(click, function () { console.log(click);})

但这而已正式发布-订户商业模式最单纯的采用,在许多情景下他们常常会采用许多自订该事件来满足用户他们的市场需求。

有许多方式能同时实现正式发布-订户商业模式,因此这儿有两个使用类的单纯同时实现。

class Emitter { constructor() { // _listener array, key is the custom event name, value is the execution callback array – as there may be more than one this._listener = [] } // 订户 窃听该事件 on(type, fn) { // Determine if the event exists in the _listener array. // Exists to push the callback to the value array corresponding to the event name, does not exist to add directly this._listener[type] ? this._listener[type].push(fn) : (this._listener[type] = [fn]) } // Publish Trigger Event trigger(type, …rest) { // Determine if the trigger event exists if (!this._listener[type]) return // Iterate through the array of callbacks executing the event and pass the parameters this._listener[type].forEach(callback => callback(…rest)) }}

如上所示,他们创建了两个 Emitter 类,并在和触发器上添加了两个原型方式,采用如下。

// Create an emitter instanceconst emitter = new Emitter()emitter.on(“done”, function(arg1, arg2) { console.log(arg1, arg2)})emitter.on(“done”, function(arg1, arg2) { console.log(arg2, arg1)})function fn1() { console.log(I am the main program) setTimeout(() => { emitter.trigger(“done”, “Asynchronous parameter I”, “Asynchronous parameter II”) }, 1000)}fn1()

他们先创建两个emitter实例,然后注册该事件,然后触发该事件,这种也解决了触发器问题。

该事件窃听的缺点和缺点

缺点:更符合模块化思想,他们在编写自己的窃听器的时候能做许多优化,从而更好的窃听流程的运行。

缺点:整个流程变为了该事件驱动,或多或少影响了流程,而且每次采用都要注册该事件窃听器然后触发,比较麻烦,标识符也不是很典雅。

3.Promise

ES6 标准化并引入了 Promise 第一类,这是一种触发器编程的软件系统。

单纯的说,就是用同步的方式写触发器标识符,能用来解决反弹冥界问题。

Promise第一类的状况一旦改变,就不能再改变,只有两种可能的改变。

由待定改为已解决。由Pending改为Rejected。

他们采用 setTimeout 来演示触发器操作方式。

function analogAsync(n) { return new Promise((resolve) => { setTimeout(() => resolve(n + 500), n); });}function fn1(n) { console.log(`step1 with ${n}`); return analogAsync(n);}function fn2(n) { console.log(`step2 with ${n}`); return analogAsync(n);}function fn3(n) { console.log(`step3 with ${n}`); return analogAsync(n);}

采用 Promise 来同时实现。

function fn() { let time1 = 0; fn1(time1) .then((time2) => fn2(time2)) .then((time3) => fn3(time3)) .then((res) => { console.log(`result is ${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;}let it = generatorFn();it.next();it.next();it.next();it.next();

上面的示例是两个具有以下特征的生成器表达式。与普通表达式不同,Generator 表达式在表达式之后和表达式名称之前有两个 *,该表达式有两个内部 yield 字段,表达式初始化后的返回值采用next方式。

Generator的缺点和缺点

缺点:典雅的流程控制方式,允许表达式被中断地继续执行。

缺点:Generator表达式的继续执行必须倚赖executor,对于只做触发器处理还是不太方便。

5.async/await

ES2017标准引入了async表达式,使得触发器操作方式更加方便。async是触发器的意思,await是async wait的简写,也就是触发器等待。async/await 被许多人认为是 js 中触发器操作方式的终极和最典雅的软件系统。

触发器在做什么?

async 表达式返回两个 Promise 第一类。如果间接在 async 表达式中返回两个间接量,async 会通过 Promise.resolve() 将间接量包装在两个 Promise 第一类中。

await 是什么?

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

假如 await 后面没有跟 Promise 第一类,则间接继续执行。

假如 await 后面跟着两个 Promise 第一类,它会堵塞后面

await 只能在触发器表达式中采用

上面采用setTimeout来演示触发器操作方式,他们采用async/await来同时实现。

async function fn() { let time1 = 0; let time2 = await fn1(time1); let time3 = await fn2(time2); let res = await fn3(time3); console.log(`result is ${res}`);}fn();

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

async/await的缺点和缺点

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

缺点:误用 await 可能会导致性能问题,因为 await 会堵塞标识符。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务