非同期処理の変遷史Promise、Generator、async/await


Promiseが解決したい問題
非同期操作は非同期操作によって出現するコールバック地獄です.
  1(function(    1){
      2(function(    2){
          3(function(    3){
              4(function(    4){
                  5(function(    5){
                      6(function(    3){
                        ...
                    })
                })
            })
        })
    })
})
Promiseを使った後
new Promise(  1)
    .then(  2(    1))
    .then(  3(    2))
    .then(  4(    3))
    .then(  5(    4))
    .then(  6(    5))
    .catch(    (    ))
まだ直観が足りないです
ソス6時代は、Promiseに基づいて、Generatorを加えました.
function *task() {
    const   1 = yield   1
    const   2 = yield   2(  1)
    const   3 = yield   3(  2)
    const   4 = yield   4(  3)
    const   5 = yield   5(  4)
    ......
}
外部実行関数
run(task)
Promise+Generator
const request = require('axios')
const { sleep } = require('./tools')

request.defaults.baseURL = 'http://127.0.0.1:3000'

function * login () {
  const {
    data: { token },
  } = yield request('/auth', { method: 'POST', data: { username: 'test', password: 'xxxxxxx' } })
  console.log('1.token->', token)
  yield sleep(2)

  const { data: roles } = yield request('/roles', { params: { token } })
  console.log('2.roles->', roles)
  yield sleep(2)

  const { data: menus } = yield request('/menus', { params: { roles } })
  console.log('3.menus->', menus)
}

function run (g) {
  const it = g() //       

  const each = res => {
    if (!res.done && res.value instanceof Promise) {
      res.value.then(v => {
        each(it.next(v)) //    yield       yield
      })
    } else if (res.done) {
      return
    } else {
      throw new Error('yield       Promise   ')
    }
  }
  each(it.next())
}

run(login)
/**
 * sleep   
 */
exports.sleep = time => {
  return new Promise(resolve => {
    console.log(`  ${time} ...`)

    setTimeout(() => {
      resolve(true)
    }, time * 1000)
  })
}
run関数はcoライブラリでも代用できます.
npm install co
const run = require('co')
......
run(login)
まだちょっと面倒です.外部に実行関数があります.
ソス8時代は、Promiseに基づいて、async/awaitを加えました.
async function task() {
    const   1 = await   1
    const   2 = await   2(  1)
    const   3 = await   3(  2)
    const   4 = await   4(  3)
    const   5 = await   5(  4)
    ......
}
Promise+async/await
const request = require('axios')

request.defaults.baseURL = 'http://127.0.0.1:3000'

/**
 * es8      async/await
 */
async function login () {
  const {
    data: { token },
  } = await request('/auth', { method: 'POST', data: { username: 'test', password: 'xxxxxxx' } })
  console.log('1.token->', token)

  const { data: roles } = await request('/roles', { params: { token } })
  console.log('2.roles->', roles)

  const { data: menus } = await request('/menus', { params: { roles } })
  console.log('3.menus->', menus)
}

login()
この関数を実行すればいいです.
職務に服してデモを行う
const app = require('express')()
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
  bodyParser.urlencoded({
    extended: true,
  }),
)

app.post('/auth', (req, res) => {
  const { username } = req.body
  console.log(username)
  res.send({
    id: 1,
    name: username,
    age: 18,
    token: `absfgsakjdhjskahdsklh`,
  })
})

app.get('/roles', (req, res) => {
  res.send([1, 2, 3])
})

app.get('/menus', (req, res) => {
  res.send([
    { name: '  ', path: '/' },
    { name: '    ', path: '/users' },
  ])
})

app.listen(3000, () => {
  console.log(`server run time: ${Date.now()}`)
})