用四種方法將兩個AJAX改為同步


用四種方法將兩個AJAX改為同步

Promise、Generator函數、yield、async/await 相關


今有一題,題目為:

  1. 現有ajax1()ajax2(),用於快速初始化CODE1和CODE2
  2. myFunc必須在CODE1和CODE2初始化之后再執行
  3. 可以在原代碼上修改

偽代碼為:

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

Ajax2({
    ...
    success: function(data){
        CODE2 = 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()

執行結果:

第一種

可以看到myFunc在兩個ajax執行完成之后才執行。

yield關鍵字

yield關鍵字是ES6添加的語法,可以在函數執行中交出運行權限

上面第一種方法一看就是不會前端的人寫的,前端如果要想炫技的話可以這么寫:

//第二種

//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 函數的含義與用法

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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM