异步操作 Async 一统江湖

245 阅读1分钟
const fs = require('fs')

第一阶段 回调函数

function readFile(path, cb) {
  fs.readFile(path, 'utf8', cb)
}

readFile('./package.json', (err, data) => {
  if (err) return console.error(err)
  console.log(data)
})

第二阶段 Promise

function readFilePromise(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, 'utf8', (err, data) => {
      err && reject(err)
      resolve(data)
    })
  })
}
readFilePromise('./package.json').then(console.log)

第三阶段 co + generator + Promise

const co = require('co')
const { promisify } = require('util')

function *read(path) {
  let data = yield promisify(fs.readFile)(path, 'utf8')
  console.log(data)
}
co(read, './package.json')

promisify原理实现

function promisify(fn) {
  return (...rest) =>
    new Promise((resolve, reject) => {
      fn(...rest, (err, data) => {
        if (err) reject(err)
        else resolve(data)
      })
    })
}
promisify(fs.readFile)('./package.json', 'utf8')
  .then(JSON.parse)
  .then(data => {
    console.log('data', data.name)
  })
  .catch(err => {
    console.log('err', err)
  })

co原理实现

function *fn(a = 0) {
  console.log('a', a)
  const b = yield Promise.resolve(2)
  console.log('b', b)
  const c = yield Promise.resolve(3)
  console.log('c', c)
  return a + b + c
}

const it = fn(1)
it.next()
it.next(2)
it.next(3)

const co = require('co')
co(fn, 1)

// co原理
run(fn, 10).then(res => {
  console.log(res)
})

function run(gen) {
  const slice = [].slice
  const args = slice.call(arguments, 1)
  return new Promise((resolve, reject) => {
    const ite = (typeof gen === 'function') && gen.apply(this, args)
    if (!ite || typeof ite.next !== 'function') return resolve(ite)
    function next(res) {
      const { value, done } = ite.next(res)
      if (done) {
        resolve(value)
      } else if (value instanceof Promise) {
        value.then(next)
      } else {
        next(value)
      }
    }
    next()
  })
}

第四阶段 Async await + Promise

const readFileAsync = promisify(fs.readFile)

async function readme(path) {
  const data = await readFileAsync(path, 'utf8')
  console.log(data)
}
readme('./package.json')