创建promise对象

我们可以通过全局构造函数Promise来创建promise对象:

const myPromise = new Promise()

Promise构造函数接受一个回调函数做为参数,而回调函数又接受两个参数;第一个参数用来收集或者捕获异步操作的结果,第二个参数用来捕获错误:

const myPromise = new Promise(function(resolve, reject) {
  if (someError) {
    reject(new Error(someError))
  } else {
    resolve('ok')
  }
})

就像之前我们提到的,当 promise 对象resolved,我们可以使用then方法获取异步操作结果;当 promise 对象rejected时,我们使用catch方法处理错误:

myPromise
  .then(function(result) {
    console.log(result)
  })
  .catch(function(error) {
    console.log(error)
  })

值得一提的是,我们将任何异步任务包装到promise中。例如,fs.readFile是一个用来异步读取文件内容的方法,我们通过下面的方式使用 fs.readFile

fs.readFile('some-file.txt', 'utf-8', function(error, content) {
  if (error) {
    return console.log(error)
  }
  console.log(content)
})

我们可以创建一个叫做readFile的函数来调用fs.readFile,读取文件内容,当读取正常时,我们使用文件内容resolve promise对象,或者使用错误信息来reject promise对象:

code/promises/wrap-readfile1.js

const fs = require('fs')
function readFile(file, format) {
  format = format || 'utf-8'
  function handler(resolve, reject) {
    fs.readFile(file, format, function(err, content) {
      if (err) {
        return reject(err)
      }
      return resolve(content)
    })
  }
  const promise = new Promise(handler)
  return promise
}

我们还可以对上面的代码进行简化:

code/promises/wrap-readfile2.js

const fs = require('fs')
function readFile(file, format = 'utf-8') {
  return new Promise((resolve, reject) => {
    fs.readFile(file, format, (err, content) => {
      if (err) return reject(err)
      resolve(content)
    })
  })
}

现在,我们可以很方便的使用上面的函数异步读取文件内容了,使用then方法获取异步结果,使用catch方法处理错误:

readFile('./example.txt')
  .then(content => console.log(content))
  .catch(err => console.log(err))

甚至,我们还可以使用Node 8中引进的util.promisify方法来进一步简化我们的代码:

code/promises/promisify-example.js

const fs = require('fs')
const util = require('util')
const readFile = util.promisify(fs.readFile)

readFile('./example.txt', 'utf-8')
  .then(content => console.log(content))
  .catch(err => console.log(err))

util.promisify方法接受一个遵循Node回调函数约定的函数,并把它变成基于 promise 的版本。你肯定会感到疑惑,为什么Node不把所有的方法都变成基于promise的,而要这样多此一举?底层Node方法都不是基于promise的,因为promise只是回调函数的上层抽象而已。是否使用这种上层抽象解决异步问题,应该交给开发者自行决定。

用户头像
登录后发表评论