Promise

10 篇文章 0 订阅

1. 回调地狱

现在我有一个需求,就是依次读取a.txt,b.txt,c.txt三个文件,我利用回调嵌套的方式,示例代码如下:

注意:如果将读取三个文件的操作不进行嵌套,而是分开写,是无法保证执行顺序的。因为读取文件操作是异步的

在这里插入图片描述

2. Promise

Promise出现的目的是解决node.js异步编程中回调地狱的问题

  • promise本身是一个构造函数,如果要使用promise去解决回调地狱的问题,先用new创建构造函数的实例对象,这个实例对象代表一个异步操作

在这里插入图片描述

  • 调用resolve就是相当于调用then方法里面的函数
  • 调用reject就相当于调用catch方法里面的函数
  • 补充:.then()也可以有两个实参来指定成功和失败的回调函数,只是第2个失败的回调函数可以省略不写

2.1 现在完成之前的需求:依次读取文件

  1. 先定义好 p1,p2,p3.分别去读取 a.txt, b.txt, c.txt 三个文件
var fs = require('fs')

var p1 = new Promise(function(resolve, reject) {
    fs.readFile('./data/a.txt', 'utf-8', function(err, data) {
        if (err) {
            reject(err)
        } else {
            resolve(data)
        }
    })
})

var p2 = new Promise(function(resolve, reject) {
    fs.readFile('./data/b.txt', 'utf-8', function(err, data) {
        if (err) {
            reject(err)
        } else {
            resolve(data)
        }
    })
})

var p3 = new Promise(function(resolve, reject) {
    fs.readFile('./data/c.txt', 'utf-8', function(err, data) {
        if (err) {
            reject(err)
        } else {
            resolve(data)
        }
    })
})
  1. 使用 .then 链式调用:
p1
    .then(function(data) {
        console.log(data)
        return p2 // p2 是一个 Promise 对象
    }, function(err) {
        console.log('读取文件失败了', err)
    })
    
    .then(function(data) {
        console.log(data)
        return p3
    })
    
    .then(function(data) {
        console.log(data);
        console.log('end');
    })

2.2改进 ------ 封装代码

可以看出 上述代码 在定义 p1,p2,p3 的时候,有很多代码重复了,我们可以进行封装。

var fs = require('fs')

// 封装的函数 pReadFile
function pReadFile(filePath) {
    return new Promise(function(resolve, reject) {
        fs.readFile(filePath, 'utf-8', function(err, data) {
            if (err) {
                reject(err)
            } else {
                resolve(data)
            }
        })
    })
}


pReadFile('./data/a.txt')
    .then(function(data) {
        console.log(data);
        return pReadFile('./data/b.txt')
    })
    .then(function(data) {
        console.log(data);
        return pReadFile('./data/c.txt')
    })
    .then(function(data) {
        console.log(data);
        console.log('end');
    })

2.3 使用第三方包:基于 then-fs 读取文件内容

由于node.js 官方提供的fs模块仅支持回调函数的方式读取文件,不支持Promise的调用方式。因此,需要先运行如下命令,安装 then-fs 这个第三方包,从而支持我们基于Promise的方式读取文件内容:

npm install then-fs
2.3.1 then-fs 的基本使用

调用then-fs 提供的readFile()方法,可以异步地读取文件的内容,它的返回值是Promise的实例对象。因此可以调用.then()方法为每个Promise异步操作指定成功失败之后的回调函数。示例代码如下:

import thenFs from 'then-fs'

thenFs.readFile('./files/a.txt','utf-8').then((r1)=>{console.log(r1);})
thenFs.readFile('./files/b.txt','utf-8').then((r2)=>{console.log(r2);})
thenFs.readFile('./files/c.txt','utf-8').then((r3)=>{console.log(r3);})

注意:此时执行node命令不一定是按顺序的,因为就如之前提到的,读取文件操作是异步操作

2.3.2 按顺序读取文件

使用 .then()方法的链式调用

import thenFs from 'then-fs'

thenFs.readFile('./files/a.txt','utf-8')
  .then((r1)=>{
    console.log(r1);
    return thenFs.readFile('./files/b.txt','utf-8')
  })
  .then((r2)=> {
    console.log(r2);
    return thenFs.readFile('./files/c.txt','utf-8')
  })
  .then((r3)=>{console.log(r3);
  })

2.4 Promise.all()方法

Promise.all()方法会发起并行的Promise异步操作,等所有的异步操作全部结束后才会执行下一步的.then操作(等待机制)。示例代码如下:

import thenFs from "then-fs";

const promiseArr = [
  thenFs.readFile('./files/c.txt','utf8'), // ccc
  thenFs.readFile('./files/a.txt','utf8'), //aaa
  thenFs.readFile('./files/b.txt','utf8') //bbb
]

Promise.all(promiseArr).then((result)=> {
  console.log(result);
})

运行结果:

[ 'ccc', 'aaa', 'bbb' ]

2.5 Promise.race()方法

Promise.race()方法会发起并行的Promise异步操作,只要任何一个异步操作完成,就立刻执行下一步的.then()操作(赛跑机制)。示例代码如下:

import thenFs from "then-fs";

const promiseArr = [
  thenFs.readFile('./files/a.txt','utf8'),
  thenFs.readFile('./files/b.txt','utf8'),
  thenFs.readFile('./files/c.txt','utf8')
]

Promise.race(promiseArr).then((result)=> {
  console.log(result);
})

运行结果是不确定的,哪个文件读取得最快就打印出来了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值