1

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(处理异常(异常信息))

还是不够直观

so es6 时代,基于 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)

还是有些麻烦,还要外部有个执行函数才行

so es8 时代,基于 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()

执行该函数即可

服务端 demo

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()}`)
})

zpfei
186 声望7 粉丝

往事如风~