使用Promise解决回调地狱的问题?

858 阅读2分钟

使用Promise解决回调地狱的问题?

一、如果使用普通的函数嵌套调用,会形成回调地狱
// 使用Promise解决回调地狱的问题

// 导入fs模块
const fs = require('fs')

function getReadFile(fpath) {
  var promise = new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {
      if (err) return reject(err)
      resolve(dataStr)
    })
  })
  // 返回promise
  return promise
}

// 需求:先读取文件1,在读取文件2,在读取文件3
// 错误的示范
getReadFile('./files/1.txt').then(
  (data) => {
    console.log(data + '读取文件1成功')
    getReadFile('./files/2.txt').then(
      (data) => {
        console.log(data + '读取文件2成功')
        getReadFile('./files/3.txt').then(
          (data) => {
            console.log(data + '读取文件3成功')
          },
          (err) => {
            console.log(err + '读取文件3失败')
          }
        )
      },
      (err) => {
        console.log(err + '读取文件2失败')
      }
    )
  },
  (err) => {
    console.log(err.message + '读取文件失败')
  }
)
二、解决办法
// 使用Promise解决回调地狱的问题

// 导入fs模块
const fs = require('fs')

function getReadFile(fpath) {
  var promise = new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {
      if (err) return reject(err)
      resolve(dataStr)
    })
  })
  // 返回promise
  return promise
}

// 需求:先读取文件1,在读取文件2,在读取文件3
// 正确的操作
getReadFile('./files/1.txt')
  .then(
    (data) => {
      console.log(data + '读取文件1成功')
      // 将promise实例返回出去,避免了回调地狱的问题
      return getReadFile('./files/2.txt')
    },
    (err) => {
      console.log(err.message + '读取文件1失败')
    }
  )
  .then(
    (data) => {
      console.log(data + '读取文件2成功')
      // 将promise实例返回出去,避免了回调地狱的问题
      return getReadFile('./files/3.txt')
    },
    (err) => {
      console.log(err.message + '读取文件2失败')
    }
  )
  .then(
    (data) => {
      console.log(data + '读取文件3成功')
    },
    (err) => {
      console.log(err.message + '读取文件3失败')
    }
  )

运行结果:

image.png

三、Promise两种捕获异常的方式?
3.1. 需求:哪怕前面的 Promise 执行失败了,但是,不要影响后续的 Promise 的执行,此时,我们可以单独为 每个 Promise, 通过 .then 指定以下失败的回调;
getReadFile('./files/1.txt')
  .then(
    (data) => {
      console.log(data + '读取文件1成功')
      return getReadFile('./files/2.txt')
    },
    (err) => {
      console.log(err.message + '读取文件1失败')
      return getReadFile('./files/2.txt')
    }
  )
  .then(
    (data) => {
      console.log(data + '读取文件2成功')
      return getReadFile('./files/3.txt')
    },
    (err) => {
      console.log(err.message + '读取文件2失败')
      return getReadFile('./files/3.txt')
    }
  )
  .then(
    (data) => {
      console.log(data + '读取文件3成功')
    },
    (err) => {
      console.log(err.message + '读取文件3失败')
    }
  )

执行结果:

image.png

3.2. 需求:后续的promise执行,依赖于 前面的Promise执行的结果,如果前面的Promise执行失败了,则后面的就没有继续执行下去的必要了,此时,一旦有报错,则终止所有的Promise

getReadFile('./files/1.txt')
  .then((data) => {
    console.log(data + '读取文件1成功')
    return getReadFile('./files/2.txt')
  })
  .then((data) => {
    console.log(data + '读取文件2成功')
    return getReadFile('./files/3.txt')
  })
  .then((data) => {
    console.log(data + '读取文件3成功')
  })
  .catch((err) => {
    // catch 的作用:如果前面有任何的Promise执行失败,则立即终止所有的Promise的执行,并马上进入catch去处理Promise中抛出的异常。
    console.log(err.message)
  })

执行结果:

image.png