node.js异步编程初探2(promise)

2022-07-28,,,,

node.js异步编程初探2

  • 问题:如果异步API后面的代码执行,依赖当前异步API的执行结果,但实际上后续代码在执行的时候异步API还没有返回结果,这个问题怎么解决?
    • 解决方案一:
    • 缺点
    • 解决方案二:
    • 解决方案三(最优):

问题:如果异步API后面的代码执行,依赖当前异步API的执行结果,但实际上后续代码在执行的时候异步API还没有返回结果,这个问题怎么解决?

例如:
如果需要一次读取多个文件。

解决方案一:

const fs = require('fs');
fs.readFile('./1.txt', 'utf8', (err, result1) => {
  console.log(reult1);
  fs.readFile('./2.txt', 'utf8', (err, result2) => {
    console.log(reult2);
    fs.readFile('./3.txt', 'utf8', (err, result3) => {
      console.log(reult3);
    })
  })
})
//输出结果
1
2
3

缺点

回调的多层嵌套,虽然能过解决需求,但会形成回调地狱的现象,不利于后期的维护。

解决方案二:

这是一种异步编程语法上的改进,可以将异步API的执行和结果的处理进行分离。
promise是构造函数。
基础代码形式:

将异步API的执行和结果的处理进行分离。

const fs = require('fs');
let promise = new Promise((resolve, reject) => {
    fs.readFile('./1.txt', 'utf8', (err, result) => {
        if (err != null) {
            reject(err);
        } else {
            resolve(result);
        }
    })
});
promise.then((result) => {
    console.log(result);
})
.catch((err) => {
    console.log(err);
})

Promise解决回调地狱的问题

//此代码有点问题,promises解决回调地狱的形式就是这样的
function p1() {
  return new Promise((resolve, reject) => {
    fs.readFile('./1.txt', 'utf8', (err, result) => {
      console.log(result);
    })
  });
}

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

function p3() {
  return new Promise((resolve, reject) => {
    fs.readFile('./3.txt', 'utf8', (err, result) => {
      console.log(result);
    })
  });
}
p1().then((r1) => {
  console.log(r1);
  return p2();
}).then((r2) => {
  console.log(r2);
  return p3();
}).then((r3) => {
  console.log(r3);
})

解决方案三(最优):

使用async关键字:
1.在普通函数前面加上async关键字,普通函数就变成了异步函数。
2.异步函数默认的返回值是promise对象,省去了需要new promise的步骤
3.在异步函数的内部使用return关键字进行结果返回,结果会被包裹在promise对象中,return关键字替代了resolve方法。
4.在异步函数的内部使用throw关键字对错误进行抛出。
5.调用异步函数再链式调用then方法获取异步函数执行结果。
6.调用异步函数再链式调用catch方法获取异步函数执行的错误信息。

例如:

async function fn() {
  throw 'err'
  return 123;
}
fn().then((data) => {
  console.log(data);
}).catch((err) => {
  console.log(err);
})

await关键字:
1.await只能出现在异步函数中
2.awiat后面只能跟promise对象,写其他类型的API是不可以的
3.await可以暂停异步函数向下执行 等待promise对象返回结果后再向下执行
由此:
异步代码------------->同步代码

const fs = require('fs');
const promisify = require('util').promisify; //promisify可对现有的异步API进行包装,让其返回promise对象
const readFile = promisify(fs.readFile); //readFile就是一个新的可以返回promise对象的方法 
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();

本文地址:https://blog.csdn.net/ryyzxf/article/details/109272882

《node.js异步编程初探2(promise).doc》

下载本文的Word格式文档,以方便收藏与打印。