Alibaba 2018 front end evaluation questions (Promise asynchronous process control)

Keywords: shell

Use Promise to control the asynchronous process. The three asynchronous tasks may be in the order of time, but they should be output in the desired order.
I use four methods to solve this problem. In fact, I want to examine your understanding of Promise, the basic problem.

//Realization mergePromise Function to execute the array in sequence,
//And then put the returned data into the array data in

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;
});



function mergePromise(ajaxArray) {
//todo Complement function
}

mergePromise([ajax1, ajax2, ajax3]).then(data => {
    console.log('done');
    console.log(data); // data by [1, 2, 3]
});

// Separate output
// 1
// 2
// 3
// done
// [1, 2, 3]

That is to complete the above mergePromise function and get the above output.

1. The best solution async

function mergePromise(ajaxArray) {
    let arr = [];
    async function run() {
        for(let ifun of ajaxArray) {
            let cur = await ifun();
            arr.push(cur);
        }
        return arr;
    }
    return run();
}

2. Construct the chain of then

function mergePromise(ajaxArray){
    let arr = [];
    let p = Promise.resolve();
    ajaxArray.forEach(item=>{
        p = p.then(data=>{
            console.log(data);
            if(data){
                arr.push(data);
            }
            return item();
        });
    })
    return p.then(data=>{
        arr.push(data);
        return arr;
    })
}

First, add a layer of promise (Promise.resolve()) in the completion state, and then construct a layer of then chain. Note that the first layer does not have data. The first layer returns item(), that is, ajax1(), which returns 1. The next step is data, that is, data is 1. The last item(), which is ajax3(), is called and returned. We need to use then to accept the result of the last step of state change, that is, the previous step Step 3 of return (return directly in promise is the state of resolve) and finally return to arr for mergerPromise to accept.

3. Recursion, another way of thinking

let timeout = function (num, ms) {
    return new Promise(function (resolve,reject) {
        setTimeout(() => {
            resolve(num);
        }, ms)
    });
}

let timeout1 = timeout(1, 500);
let timeout2 = timeout(2, 2000);
let timeout3 = timeout(3, 1000);

let myPromise = new Promise(function (resolve,reject) {

    let arr = [];
    let timeouts = [timeout1,timeout2,timeout3];
    runIndex(0);
    function runIndex(index){
        timeouts[index].then(data=>{
            console.log(data)
            arr.push(data);
            if(index<timeouts.length-1) {
                console.log('index',index);
                index++;
                runIndex(index);
            }else {
                resolve(arr);
            }

        })
    }
});


myPromise.then(data => {
    console.log(data);
    console.log("done!");
})

I think it's a bug to do this problem recursively, which is to make full use of the change of recursive domain environment.

4. The most violent direct handwritten chain

function mergePromise(ajaxArray) {
    let arr = [];
    // ajaxArray[0]();
    return ajaxArray[0]().then(data=>{
        arr.push(data);
        return ajaxArray[1]();
    }).then(data=>{
        arr.push(data);
        return ajaxArray[2]();
    }).then(data=>{
        arr.push(data);
        return arr;
    })
}

That is to say, the expansion of the last cycle has the advantage that there is no need to add a layer of resolve shell.

At the end of the day, I'd like to leave a comment.

Posted by eosinophil on Fri, 03 Jan 2020 12:15:57 -0800