Skip to content

js解决异步回调地狱方式

548字约2分钟

JavaScript

2020-12-05

回调函数

当想使js中异步多个api按照一定顺序运行时,最原始办法只能用回调函数套回调函数,这样外面执行完,里面函数再执行。

const fs = require('fs');

fs.readFile('./1.txt', 'utf8', (err, result1) => {
 console.log(result1)
 fs.readFile('./2.txt', 'utf8', (err, result2) => {
  console.log(result2)
  fs.readFile('./3.txt', 'utf8', (err, result3) => {
   console.log(result3)
  })
 })
});

Promise

当异步任务过多时,嵌套方式将会比较复杂不利于书写和维护,于是就有了Promise对象

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。

Promise 也有一些缺点。

  • 无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
  • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  • 当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

const fs = require('fs');
function p1 () {
 return new Promise ((resolve, reject) => {
  fs.readFile('./1.txt', 'utf8', (err, result) => {
   resolve(result)
  })
 });
}

function p2 () {
 return new Promise ((resolve, reject) => {
  fs.readFile('./2.txt', 'utf8', (err, result) => {
   resolve(result)
  })
 });
}

function p3 () {
 return new Promise ((resolve, reject) => {
  fs.readFile('./3.txt', 'utf8', (err, result) => {
   resolve(result)
  })
 });
}

p1().then((r1)=> {
 console.log(r1);
 return p2();
})
.then((r2)=> {
 console.log(r2);
 return p3();
})
.then((r3) => {
 console.log(r3)
})

async/await

  1. 在普通函数定义的前面加上async关键字 普通函数就变成了异步函数
  2. 异步函数默认的返回值是promise对象
  3. 在异步函数内部使用throw关键字进行错误的抛出

await关键字

  1. 它只能出现在异步函数中
  2. await promise 它可以暂停异步函数的执行 等待promise对象返回结果后再向下执行函数
const fs = require('fs');
// 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法
const promisify = require('util').promisify;
// 调用promisify方法改造现有异步API 让其返回promise对象
const readFile = promisify(fs.readFile);

async function run () {
 let r1 = await readFile('./1.txt', 'utf8')
 let r2 = await readFile('./2.txt', 'utf8')
 let r3 = await readFile('./3.txt', 'utf8')
 console.log(r1)
 console.log(r2)
 console.log(r3)
}

run();