如何在Node中使用Promise

一、回调地狱的产生

例如下面一段代码,分别访问三个文件,因为都是异步操作,所以无法保证执行结果的顺序]


var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function (err, data) {
  if (err) {
  throw err
}

var fs = require('fs')

fs.readFile('./data/b.txt', 'utf8', function (err, data) {
  if (err) {
  throw err
}

var fs = require('fs')

fs.readFile('./data/c.txt', 'utf8', function (err, data) {
  if (err) {
  throw err
}

如何解决保证执行结果的顺序?
可以使用回调函数进行嵌套


var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function (err, data) {
  if (err) {
    throw err
  }
  console.log(data)
  fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
    throw err
    }
    console.log(data)
    fs.readFile('./data/c.txt', 'utf8', function (err, data) {
      if (err) {
      throw err
      }
      console.log(data)
    })
  })
})

如果嵌套的次数太多就会产生回调地狱

二、Promise基本语法

为了解决以上编码方式带来的回调地狱嵌套,所以在ES6中新增了一个API:promise(一个构造函数)
promise是一个容器,容器中存放了一个异步任务,promise本身不是异步,但是内部封装了一个异步任务— pending,pending的结果只能变为两种:

  • Resolved: 被解决的(成功)
  • Rejected:被拒绝的 (失败)

1. 创建Promise容器

promise 容器一旦被创建就会执行里面的代码。
我创建了一个data目录下的a.txt文件,使用promise访问里面的数据


var fs = require('fs')

new Promise(function(){
    fs.readFile('./data/a.txt', 'utf8', function(err, data){
        if(err){
            console.log(err)
        }else{
            console.log(data)
        }
    })
})

但是其实,promisse的访问是异步操作,如下所示:


var fs = require('fs')
console.log(1)
new Promise(function(){
    console.log(2)
    fs.readFile('./data/a.txt', 'utf8', function(err, data){
        if(err){
            console.log(err)
        }else{
            console.log(3)
            console.log(data)
        }
    })
})
console.log(4)

异步结果

2. 如何获取成功和失败的数据

使用promise实例对象的then方法


var fs = require('fs')

var p1 = new Promise(function (resolve, reject) {
  fs.readFile('./data/a.txt', 'utf8', function (err, data) {//异步任务
    if (err) {
    //失败调用
    //调用的reject就相当于调用then方法的第二个参数-function err
      reject(err)
    } else {
    //成功调用
    //调用的resolve方法实际上就是then方法传递的那个function data
      resolve(data)
    }
  })
})


p1
  .then(function (data) {
    console.log(data)
 
  }, function (err) {
    console.log('读取文件失败了', err)
  })


3. 解决嵌套问题

当 p1 读取成功的时候,当前函数中 return 的结果就可以在后面的 then 中 function 接收到
当你 return 123 后面就接收到 123
return ‘hello’ 后面就接收到 ‘hello’
没有 return 后面收到的就是 undefined
我们可以 return 一个 Promise 对象
当 return 一个 Promise 对象的时候,后续的 then 中的 方法的第一个参数会作为 p2 的 resolve


var fs = require('fs')

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

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

var p3 = new Promise(function (resolve, reject) {
  fs.readFile('./data/c.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

p1
  .then(function (data) {
    console.log(data)
	return p2
  }, function (err) {
    console.log('读取文件失败了', err)
  })
  .then(function (data) {//该方法作为p2的resolve
    console.log(data)
    return p3
  })
  .then(function (data) {//该方法作为p3的resolve
    console.log(data)
    console.log('end')
  })

结果输出三个文件中的数据,同时读取的顺序不会错

4. 封装Promise版本的readFile


var fs = require('fs')

function pReadFile(filePath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(filePath, 'utf8', 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)
  })

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值