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