异步发展过程

183 阅读2分钟

1 callback

代码:

function sleepByCb(cb) {
  setTimeout(function () {
    cb()
  }, 1000)
}

function testCb() {
  console.log('开始输出')
  sleepByCb(function () {
    console.log('1s后输出')
    sleepByCb(function () {
      console.log('2s后输出')
      sleepByCb(function () {
        console.log('3s后输出')
        sleepByCb(function () {
          console.log('4s后输出')
          sleepByCb(function () {
            console.log('5s后输出')
          })
        })
      })
    })
  })
  console.log('立即输出')
}

testCb()

testCb()

输出:

开始输出
立即输出
1s后输出
2s后输出
3s后输出
4s后输出
5s后输出

总结: 使用回调简单粗暴,但是对于回调嵌套回调的情况下,简直是没办法看

2 promise

代码:

function sleepByPromise() {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve()
    }, 1000)
  })
}

function testPromise() {
  console.log('开始输出:promise')
  sleepByPromise()
    .then(function () {
      console.log('1s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('2s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('3s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('4s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('5s后输出')
      return sleepByPromise()
    })
  console.log('立即输出')
}

testPromise()

输出:

开始输出:promise
立即输出
1s后输出
2s后输出
3s后输出
4s后输出
5s后输出

总结: 这种链式的写法让函数的流程比较清楚了,抛弃了嵌套。但并没有解决回调本身。

3 generator

代码:

function sleepByPromise() {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve()
    }, 1000)
  })
}

function testPromise() {
  console.log('开始输出:promise')
  sleepByPromise()
    .then(function () {
      console.log('1s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('2s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('3s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('4s后输出')
      return sleepByPromise()
    })
    .then(function () {
      console.log('5s后输出')
      return sleepByPromise()
    })
  console.log('立即输出')
}

// testPromise()

// 3 generator
function sleepByPromise() {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve()
    }, 1000)
  })
}

function* testGenerator() {
  console.log('开始输出:generator')
  yield sleepByPromise()
  console.log('1s后输出')
  yield sleepByPromise()
  console.log('2s后输出')
  yield sleepByPromise()
  console.log('3s后输出')
  yield sleepByPromise()
  console.log('4s后输出')
  yield sleepByPromise()
  console.log('5s后输出')
  console.log('立即输出')
}

let it = testGenerator()
it.next().value
  .then(() => {
    return it.next().value
  })
  .then(() => {
    return it.next().value
  })
  .then(() => {
    return it.next().value
  })
  .then(() => {
    return it.next().value
  })
  .then(() => {
    return it.next().value
  })

输出:

开始输出:generator
1s后输出
2s后输出
3s后输出
4s后输出
5s后输出
立即输出

总结: 使用generator+promise使异步更像是同步(具有流程性),但是还是需要自己调用遍历比较繁琐。使用TJ大神的co库可以不用自己手动进行下一次遍历。

4 generator+co

代码:

 const co = require("co");

// 同上    
    
  co(testGenerator())

输出:

开始输出:generator
1s后输出
2s后输出
3s后输出
4s后输出
5s后输出
立即输出

5 async/await

代码:

// 5 async/await
function sleepByPromise() {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve()
    }, 1000)
  })
}

async function testAsyncAwait() {
  console.log('开始输出:generator')
  await sleepByPromise()
  console.log('1s后输出')
  await sleepByPromise()
  console.log('2s后输出')
  await sleepByPromise()
  console.log('3s后输出')
  await sleepByPromise()
  console.log('4s后输出')
  await sleepByPromise()
  console.log('5s后输出')
  console.log('立即输出')
}

testAsyncAwait()

输出:

开始输出:async/await
1s后输出
2s后输出
3s后输出
4s后输出
5s后输出
立即输出

总结: 这个只是generator+promise的语法糖,但它能将原本异步的代码写成同步的形式