阿里前端测试题:实现mergePromise函数
原题
实现 mergePromise 函数,把传进去的数组顺序先后执行,并且把返回的数据先后放到数组 data 中。
const timeout = ms =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ms)
})
const ajax1 = () =>
timeout(2000).then(() => {
console.log('1')
return 1
})
const ajax2 = () =>
timeout(1000).then(() => {
console.log('2')
return 2
})
const ajax3 = () =>
timeout(2000).then(() => {
console.log('3')
return 3
})
const mergePromise = ajaxArray => {
// 在这里实现你的代码
}
mergePromise([ajax1, ajax2, ajax3]).then(data => {
console.log('done')
console.log(data) // data 为 [1, 2, 3]
})
// 分别输出
// 1
// 2
// 3
// done
// [1, 2, 3]解题思路
这题主要是希望使用同步的方法线性的执行函数ajax1, ajax2, ajax3,在本题中,函数ajax是一个定时器,在设制定时器后执行异步打印,因为ajax2设置的时间小于ajax1和ajax3,所以如果线性调用的话,正常来说ajax2会早于ajax1和ajax3返回,所以在做这一题时的核心思路就是只有当前函数完全执行完毕后,才会进行下一个函数的执行。
我的答案
const mergePromise = ajaxArray => {
// 在这里实现你的代码
return new Promise(async function(resolve) {
let data = []
for (let it of ajaxArray) {
let tmp = await it()
data.push(tmp)
}
resolve(data)
})
}利用async函数只有在前一个await返回后才会才会进入下一个await的特点,实现线性执行异步函数。如此在循环中每次遇到await时,都会等待ajax函数返回才会继续后面的语句,这样就可以用同步的方式执行完所有的异步函数了。
网上的其他答案
const mergePromise = ajaxArray => {
// 在这里实现你的代码
var data = []
var sequence = Promise.resolve()
ajaxArray.forEach(function(item) {
sequence = sequence.then(item).then(function(res) {
data.push(res)
return data
})
})
return sequence
}怎么说呢,这个答案就比较高深了,第一眼完全没有看懂,仔细分析之后,才大致有了个概念。
首先,因为mergePromise只是一个普通函数,不可能会有.then方法,所以他在mergePromise函数中,返回了sequence对象,这个对象返回的是Promise.resolve(),从而达到后续代码可以正常执行的目的。
第二,通过forEach方法,执行了数组中的每个函数,根据Promise的特性,在前一个then未执行完时,是不会进行后面then的执行的,所以他在sequence.then(item).then(function(res){...})这个流程中,线性的执行完了每一个ajax函数。
第三,根据Promise的特性,每一个then的返回值都是一个Promise对象,所以即使在前面只是执行了Promise.resolve(),他也可以在后面通过return data把data传递给Promise对象,保证了后面执行mergePromise([ajax1, ajax2, ajax3]).then(data => {...})时,then可以正常接收到传参。