面试题目(字节)——异步顺序处理数据
场景
一个问题自己过程中想了很长时间没有解决出来,特此记录一下
let timeout = (ms) => {
return new Promise(resolve => {
setTimeout(resolve, ms)
})
}
let ajax1 = () => timeout(2000).then(data => {
console.log('1')
return 1
})
let ajax2 = () => timeout(1000).then(data => {
console.log('2')
return 2
})
let ajax3 = () => timeout(500).then(data => {
console.log('3')
return 3
})
promiseArr([ajax1, ajax2, ajax3]).then(data => {
console.log('done')
console.log(data)
})
// 希望数据顺序执行为 '1', '2', '3', 'done', [1, 2, 3]
这个问题开始看的时候就知道肯定是顺序异步执行 ajax1 -> ajax2 -> ajax3, 但是这个return把我卡住了。之后好好看了看Promise 执行then方法仍然可以执行 then,一下子豁然开朗,测试代码如下
let p = new Promise(resolve => {
resolve()
})
console.log(p) // Promise { undefined }
let testPromise = p.then(data => console.log('1'))
console.log(testPromise) // Promise { <pending> }
testPromise.then(data => console.log(1)) // 1
testPromise仍然是一个promise对象,仍然后边可以跟then,既然是promise,就可以使用async,await 来优雅解决这个问题
const promiseArr = (ajaxArr) => {
return new Promise(async resolve => {
let arr = [];
for(let ajax of ajaxArr) {
let data = await ajax()
arr.push(data)
}
resolve(arr)
})
}
不用async,await的话也可以用递归来处理
const promiseArr = (ajaxArr) => {
return new Promise(resolve => {
let arr = [], i = 0
const next = () => {
ajaxArr[i]().then(data => {
i ++;
arr.push(data)
if(i < ajaxArr.length) {
next()
}else {
resolve(arr)
}
})
}
next()
})
}
读文档时发现也可以利用reduce 方法来处理,需要为初始值赋值Promise.resolve(),实现如下
const promiseArr = (ajaxArr) => {
return new Promise(resolve => {
let arr = []
ajaxArr.reduce((start, nextPromise) => {
return start.then(nextPromise).then(data => {
arr.push(data)
if(arr.length === ajaxArr.length) {
resolve(arr)
}
})
}, Promise.resolve())
})
}
第一种方式是最优雅的
小结
归根结底这都是事后诸葛亮,还是因为自己对基础的掌握不足而在面试中没有解决出这个问题,还是要多多努力,继续冲!