天天看點

兩個ajax如何實作同步,用四種方法将兩個AJAX改為同步

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

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

今有一題,題目為:

現有ajax1()和ajax2(),用于快速初始化CODE1和CODE2

myFunc必須在CODE1和CODE2初始化之後再執行

可以在原代碼上修改

僞代碼為:

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

執行結果:

可以看到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() {

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)