javascript 4种常见的异步写法

我们通过一个案例来总结异步写法,案例通过setTimeout来模拟异步,起作用就是输入什么就返回什么,要实现的目标是连续三次互相依赖的串行异步调用并把结果拼接出来。

写法1:回调函数

优点:

  1. 简单,也是最容易想到的写法;

缺点:

  1. 不利于代码的阅读和维护,容易写出回调地狱
  2. 每个任务只能指定一个回调函数;
  3. 不能使用 try catch 捕获错误,不能直接return;
function asyncCallback(content, callback) {
  setTimeout(callback, 200, content);
}

asyncCallback('1111', (content) => {
  console.log(content);
  asyncCallback(`${content}2222`, (content) => {
    console.log(content);
    asyncCallback(`${content}3333`, (content) => {
      console.log(content);
    });
  });
});
复制代码

写法2:事件监听

优点:

  1. 可绑定多个事件,每个事件可以指定多个回调函数;
  2. 解决了回调地狱,能实现解耦,有利于实现模块化。

缺点:

  1. 整个程序都要变成事件驱动型,运行流程会变得很不清晰
  2. 可读性较差,难以梳理出程序主流程。
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();

function asyncEvent(content, eventType) {
  setTimeout(() => {
    eventEmitter.emit(eventType, content);
  }, 200);
}

let globalContent = '';
asyncEvent('1111', 'event1');
eventEmitter.on('event1', (content) => {
  globalContent = `${globalContent}${content}`;
  console.log(globalContent);
  asyncEvent('2222', 'event2');
});
eventEmitter.on('event2', (content) => {
  globalContent = `${globalContent}${content}`;
  console.log(globalContent);
  asyncEvent('3333', 'event3');
});
eventEmitter.on('event3', (content) => {
  globalContent = `${globalContent}${content}`;
  console.log(globalContent);
});
复制代码

写法3:promise

优点:

  1. 解决了回调地狱,代码相对简洁直观
  2. 能够通过回调函数捕获错误

缺点:

  1. 无法取消Promise,一旦新建它就会执行,无法中途取消
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
  3. 当处于Pending状态时,无法得知当前进度(刚刚开始还是即将完成)。
function asyncPromise(content) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(content);
    }, 200);
  });
};

asyncPromise('1111').then((data) => {
  console.log(data);
  return asyncPromise(`${data}2222`);
}).then((data) => {
  console.log(data);
  return asyncPromise(`${data}3333`);
}).then((data) => {
  console.log(data);
  return asyncPromise(`${data}3333`);
}).catch((err) => {
  console.log(err);
})
复制代码

写法4:async/await

优点:

  1. 代码十分简洁直观,优雅地解决回调地狱问题;
  2. 适用性更广泛,await 命令后面,可以跟 Promise 对象和原始类型的值;
  3. 语义性更强,使得异步代码读起来像同步代码

缺点:

  1. 多个没有依赖性的异步代码使用await时,会导致性能上的降低。
async function asyncPromise(content) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(content);
    }, 200);
  });
};
async function getContent() {
  const content1 = await asyncPromise('1111');
  const content2 = await asyncPromise('2222');
  const content3 = await asyncPromise('3333');
  console.log(`${content1}${content2}${content3}`);
}
getContent();
复制代码

参考文档:zhuanlan.zhihu.com/p/57548254

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享