美文网首页
14.回调地狱与 Promise

14.回调地狱与 Promise

作者: 璎珞纨澜 | 来源:发表于2019-04-16 15:11 被阅读0次

回调地狱

为了保证异步代码的执行顺序,将异步代码嵌套到回调函数中,当异步的方法多了,就会产生回调地狱(callback hell),这样的代码丑陋且难以维护。


回调地狱

读取三个文件 - 无法保证顺序的代码:

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)
})

读取三个文件 - 通过回调嵌套的方式来保证执行顺序:

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)
    })
  })
})

ES6 Promise

参考文档:http://es6.ruanyifeng.com/#docs/promise

为了解决以上编码方式带来的问题(回调地狱嵌套),所以在 EcmaScript 6 中新增了一个 API:Promise

  • Promise 是一个容器,容器中保存着某个异步任务操作的结果。从语法上说,Promise 是一个对象,从它可以获取异步任务操作的消息。Promise 本身不是异步,但内部往往都是封装一个异步任务。
    • 三种任务状态
      • 默认状态:Pending 进行中
      • 任务成功:Resolved 已完成
      • 任务失败:Rejected 已失败
    • 两种状态变化
      • Pending => Resolved
      • Pending => Rejected

基本用法:

var fs = require ('fs')

// 创建 Promise 容器
var promise = new Promise(function (resolve, reject) { // 这里的 function 是异步任务
  if (err) {
    reject(err) // 任务失败,把容器的 Pending 状态变为 Rejected
  } else {
    resolve(data) // 任务成功,把容器的 Pending 状态变为 Resolved
  }
})

promise
  .then(function (data) { 
    console.log(data) // 第一个参数: function 就是容器中的 resolve 函数
  }, function (err) {
    console.log('读取文件失败了',err) // 第二个参数: function 就是容器中的 reject 函数
  })

读取三个文件 - 使用 Promise 的方式来保证执行顺序:

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('读取a文件失败了', err)
  })
  .then(function (data) {
    console.log(data)
    return p3
  }, function (err) {
    console.log('读取b文件失败了', err)
  })
  .then(function (data) {
    console.log(data)
    console.log('end')
  }, function (err) {
    console.log('读取c文件失败了', err)
  })

解读:

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

封装 Promise API

上面的代码示例解决了嵌套代码不美观的问题,但是没有解决代码重复冗余的问题,因此我们这里把 Promise 封装成可以重复调用的 API

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')
  }, function (err) {
    console.log('读取a文件失败了', err)
  })
  .then(function (data) {
    console.log(data)
    return pReadFile('./data/c.txt')
  }, function (err) {
    console.log('读取b文件失败了', err)
  })
  .then(function (data) {
    console.log(data)
  }, function (err) {
    console.log('读取c文件失败了', err)
  })

相关文章

  • Promise

    1.为什么需要Promise 回调地狱回调函数中嵌套回调Promise解决了回调地狱 2. Promise 的基本...

  • 14.回调地狱与 Promise

    回调地狱 为了保证异步代码的执行顺序,将异步代码嵌套到回调函数中,当异步的方法多了,就会产生回调地狱(callba...

  • ES6(十一)—— Promise(更优的异步编程解决方案)

    目录 说到Promise就不得不说道说道这 —— 回调地狱 Promise —— 解决回调地狱Promise语法规...

  • promise和async

    Promise 回调地狱 Promise概念 Promise是ES6中新增的一个构造函数。 目的解决回调地狱的问题...

  • ES6快速学习(七)Promise

    回调函数 Promise 解决了什么痛点 回调地狱 代码如下 我的第一个Promise使用 解决回调地狱之链式...

  • 个人笔记

    同步/异步 回调函数=> 回调地狱 setInterval/setTimeout =>Promise=>Gener...

  • promise

    promise解决回调地狱, 实现链式操作

  • Promise、Generator、Reflect、Map入门、

    Promise Promise的出现是为了解决回调地狱的,使用Promise,我们就可以利用then进行「链式回调...

  • node 异步编程

    回调函数方式缺点:回调地狱、异步并发控制困难 Promise Async / Await

  • 总结知识点

    1:promise解决了回调地狱和异步async和await var promise = new Promise(...

网友评论

      本文标题:14.回调地狱与 Promise

      本文链接:https://www.haomeiwen.com/subject/jgnpwqtx.html