用四種方法將兩個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)

相關文章
相關標籤/搜索