用四种方法将两个AJAX改成同步

用四种方法将两个AJAX改成同步

Promise、Generator函数、yield、async/await 相关html


今有一题,题目为:前端

  1. 现有ajax1()ajax2(),用于快速初始化CODE1和CODE2
  2. myFunc必须在CODE1和CODE2初始化以后再执行
  3. 能够在原代码上修改

伪代码为:ajax

Ajax1({
    ...
    success: function(data){
        CODE1 = data
    }
})

Ajax1({
    ...
    success: function(data){
        CODE1 = data
    }
})

myFunc(CODE1, CODE2)

立Flag判断

做为一个后端,我最早想到的是建立一个变量来标志两个ajax是否完成,而后再两个ajax的回调中进行判断(至于两个ajax都改成同步这种方法直接不考虑),大体代码以下:后端

使用了setTimeOut来模拟ajax:数组

let CODE1 = null
let CODE2 = null
function myFunc() {
  console.log(CODE1, CODE2);
}

//第一种
let flag = 0 //flag默认为0

function ajax1() {
  setTimeout(() => {
    console.log('ajax1获得响应')
    CODE1 = 'ajax1返回的数据'
    //若是回调时flag为1,表明另外一个ajax已经初始化成功
    if (flag === 1) {
      myFunc()
    } else {
      //不然flag+1表明本ajax成功
      flag += 1
    }
  }, 1000)
}

function ajax2() {
  setTimeout(() => {
    console.log('ajax2获得响应')
    CODE2 = 'ajax2返回的数据'

    if (flag === 1) {
      myFunc()
    } else {
      flag += 1
    }
  }, 2000)
}

ajax1()
ajax2()

执行结果:promise

第一种

能够看到myFunc在两个ajax执行完成以后才执行。async

yield关键字

yield关键字是ES6添加的语法,能够在函数执行中交出运行权限函数

上面第一种方法一看就是不会前端的人写的,前端若是要想炫技的话能够这么写:code

//第二种

//Promise执行器
function run(gen) {
  gen = gen()
  return next(gen.next())

  function next({ done, value }) {
    return new Promise(resolve => {
      if (done) {
        resolve(value)
      } else {
        value.then(data => {
          next(gen.next(data)).then(resolve)
        })
      }
    })
  }
}

function ajax1() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('ajax1获得响应');
      CODE1 = 'ajax1返回的数据'
      resolve()
    }, 5000)
  })
}

function ajax2() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('ajax2获得响应');
      CODE2 = 'ajax2返回的数据'
      resolve()
    }, 5000)
  })
}

function* call() {
  let aj1 = ajax1()
  let aj2 = ajax2()
  yield aj1
  yield aj2
}

run(call).then(myFunc)

什么意思我解释不清楚,也不想解释,本身去看阮一峰的博客:Generator 函数的含义与用法htm

async/await关键字

async/await关键字是ES7的语法,是对上面Promise执行器的一种简化:

// 第三种

function ajax1() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('ajax1获得响应');
      CODE1 = 'ajax1返回的数据'
      resolve()
    }, 1000)
  })
}

function ajax2() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('ajax2获得响应');
      CODE2 = 'ajax2返回的数据'
      resolve()
    }, 2000)
  })
}

async function call() {
    /* 
    这里不能这么写:
    await ajax1()
    await ajax2()
    这样会在ajax1以后才会执行ajax2
    须要写成下面的这种:
    */
  let aj1 = ajax1()
  let aj2 = ajax2()
  await aj1
  await aj2
  myFunc()
}

call()

async声明这是一个内部存在同步的函数,只有声明了async,函数内部才能使用await,await表明等待Promise执行完毕才会继续执行,的确有点同步的感受了。

Promise

上面用到了Promise可是都没介绍,就是想把最合适的一种放到最后:

//第四中,同时也是最优解

function ajax1(resolve, reject) {
    setTimeout(()=>{
        console.log('ajax1获得响应');   
        CODE1 = 'ajax1返回的数据'
        resolve()
    },1000)
}

function ajax2(resolve, reject) {
    setTimeout(()=>{
        console.log('ajax2获得响应');   
        CODE2 = 'ajax2返回的数据'
        resolve()
    },2000)
}

const p1 = new Promise(ajax1)
const p2 = new Promise(ajax2)

Promise.all([p1, p2]).then(myFunc)

函数Promise.all()接收一个Promise数组参数,做用是数组内的Promise执行完毕以后会返回一个Promise对象。(还有一个Promise.race()方法也挺好玩,做用是参数中任意一个Promise完成就返回一个Promise)

相关文章
相关标签/搜索