instructions

Recently in the review of Promise knowledge, so I did some questions, here selected a few questions, we have a look.

Subject to a

const promise = new Promise((resolve, reject) = > {
    console.log(1);
    resolve();
    console.log(2);
})

promise.then((a)= > {
    console.log(3);
})

console.log(4);
Copy the code

parsing

First, a Promise executes immediately after it is created, so it prints 1,2 first, while the code inside promise.then () executes immediately at the end of the next event loop, so it continues to print 4, and finally prints 3.

The answer

1
2
4
3
Copy the code

Topic 2

const promise = new Promise((resolve, reject) = > {
    resolve('success1');
    reject('error');
    resolve('success2');
});

promise.then((res) = > {
    console.log('then:', res);
}).catch((err) = > {
    console.log('catch:', err);
})
Copy the code

parsing

The resolve function changes the state of the Promise object from “unfinished” to “successful” (that is, from pending to Resolved), calls it when the asynchronous operation succeeds, and passes the result of the asynchronous operation as an argument.

The Reject function changes the state of the Promise object from “unfinished” to “failed” (that is, from pending to Rejected), calls it when the asynchronous operation fails, and passes the error reported by the asynchronous operation as an argument.

And once the state changes, it never changes. So the code reject(‘error’); It won’t work.

A Promise can only be resolved once, and any other calls are ignored. So the second resolve(‘success2’); It’s not going to work.

The answer

then: success1
Copy the code

The title three

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
Copy the code

parsing

The Promise. Resolve method returns a new Promise object in the resolved state, if the parameter is a raw value or an object that does not have then methods. The arguments to the promise. resolve method are also passed to the callback function.

The then method takes a function as an argument, and if it passes something other than a function, it actually interprets it as THEN (NULL), which causes the result of the previous Promise to penetrate below.

The answer

1
Copy the code

The title four

The red light is on once in three seconds, the green light is on once in one second, and the yellow light is on once in two seconds; How do I make three lights turn on again and again? Three lighting functions already exist (implemented with Promse) :

function red() {
    console.log('red');
}
function green() {
    console.log('green');
}
function yellow() {
    console.log('yellow');
}
Copy the code

parsing

Three seconds on a red light, green light for a second time, yellow light 2 seconds on time, which means that for 3 seconds, performs a function of red, 2 seconds, perform a green function, 1 second to perform a yellow function, alternating repeated lights, which means that in this order has been executed this three functions, this step can use recursion to achieve.

The answer

function red() {
    console.log('red');
}
function green() {
    console.log('green');
}
function yellow() {
    console.log('yellow');
}

var light = function (timmer, cb) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            cb();
            resolve();
        }, timmer);
    });
};

var step = function () {
    Promise.resolve().then(function () {
        return light(3000, red);
    }).then(function () {
        return light(2000, green);
    }).then(function () {
        return light(1000, yellow);
    }).then(function () {
        step();
    });
}

step();
Copy the code

Topic five

Implement the mergePromise function, which executes the array passed in in sequence, and places the returned data in the array data in sequence.

const timeout = ms= > new Promise((resolve, reject) = > {
    setTimeout((a)= > {
        resolve();
    }, ms);
});

const ajax1 = (a)= > timeout(2000).then((a)= > {
    console.log('1');
    return 1;
});

const ajax2 = (a)= > timeout(1000).then((a)= > {
    console.log('2');
    return 2;
});

const ajax3 = (a)= > timeout(2000).then((a)= > {
    console.log('3');
    return 3;
});

const mergePromise = ajaxArray= > {
    // Implement your code here

};

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

// Request separate output
/ / 1
/ / 2
/ / 3
// done
/ / [1, 2, 3]
Copy the code

parsing

Ajax1, ajax2, and ajax3 are all functions, but they return a Promise when executed. We just execute them sequentially and put the result in data, but these functions are all asynchronous and want to execute them sequentially, and then print 1,2, 3 is not that simple. Let’s see.

function A() {
    setTimeout(function () {
        console.log('a');
    }, 3000);
}

function B() {
    setTimeout(function () {
        console.log('b');
    }, 1000);
}

A();
B();

// b
// a
Copy the code

In the example, we execute A sequentially, B but the output is B, A for these asynchronous functions, it does not execute one sequentially and then the next. So we’re going to use Promise to control asynchronous flow, and we’re going to have to figure out how to make one of these functions execute, and then execute the next one. Let’s see.

The answer

// Save the result of executing the functions in the array
var data = [];

The resolve method is called with no arguments and returns an Resolved Promise object.
var sequence = Promise.resolve();

ajaxArray.forEach(function (item) {
    // The first then method executes each function in the array,
    // The second then method takes the result of the array function's execution,
    // Add the result to data and return data.
    // The sequence reassignment extends the Promise chain
    sequence = sequence.then(item).then(function (res) {
        data.push(res);
        return data;
    });
})

// When the loop is complete, return a Promise, i.e., sequence, whose [[PromiseValue]] value is data,
// Data (which holds the result of the execution of the function in the array) is passed as an argument to the next call to the then method.
return sequence;
Copy the code

Topic 6

What does the following code output?

const first = (a)= > (new Promise((resolve, reject) = > {
    console.log(3);
    let p = new Promise((resolve, reject) = > {
        console.log(7);
        setTimeout((a)= > {
            console.log(5);
            resolve(6);
        }, 0)
        resolve(1);
    });
    resolve(2);
    p.then((arg) = > {
        console.log(arg);
    });

}));

first().then((arg) = > {
    console.log(arg);
});
console.log(4);
Copy the code

parsing

In fact, this problem is not much related to Promise, mainly need to understand the JS implementation mechanism, in order to solve this problem, for the JS implementation mechanism do not know friends recommend to see this article

This time, thoroughly understand the JavaScript execution mechanism

The first event loop

First execute the macro task, the main script, new Promise immediately execute, print [3], execute the new Promise operation p, print [7], find setTimeout, put the callback into the next task Queue (Event Queue), p then, Let’s call it then1 and put it on the microtask queue, and then that finds first, let’s call it then2 and put it on the microtask queue. Execute console.log(4), output [4], and the macro task is finished. Then execute the micro task, execute then1, output [1], execute then2, output [2]. This is the end of the first event loop. Start the second round.

Second cycle of events

First execute the callback of setTimeout in the macro task, and output [5]. Resolve (6) will not take effect, because once the state of p changes, it will not change again.

The answer

3
7
4
1
2
5 
Copy the code

Title seven

There are eight image resource urls already stored in an array of urls (urls = [‘http://example.com/1.jpg’,…., ‘http://example.com/8.jpg’]), There is already a function called function loadImg that enters a URL link and returns a Promise that will resolve and reject when the image is downloaded. However, we require that no more than three links be downloaded at any one time. Write a piece of code to implement this requirement, requiring all images to be downloaded as quickly as possible.

var urls = ['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg'.'https://www.kkkk1000.com/images/getImgData/gray.gif'.'https://www.kkkk1000.com/images/getImgData/Particle.gif'.'https://www.kkkk1000.com/images/getImgData/arithmetic.png'.'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif'.'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg'.'https://www.kkkk1000.com/images/getImgData/arithmetic.gif'.'https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be40ccc434be0~tplv-t2oaga2asx-image.image'];
function loadImg(url) {
    return new Promise((resolve, reject) = > {
        const img = new Image()
        img.onload = function () {
            console.log('One image is loaded');
            resolve();
        }
        img.onerror = reject
        img.src = url
    })
};
Copy the code

parsing

When one image is loaded, we will continue to request another image, keeping the number of concurrent requests at 3, until all images are loaded.

Promises are an array of promises. Call promises. Race repeatedly to return promises that change their state the fastest. Then delete promises from the array (Promises) and add a new Promise until all urls are taken. Finally, use promise. all to make promises that have not changed state.

The answer

var urls = ['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg'.'https://www.kkkk1000.com/images/getImgData/gray.gif'.'https://www.kkkk1000.com/images/getImgData/Particle.gif'.'https://www.kkkk1000.com/images/getImgData/arithmetic.png'.'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif'.'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg'.'https://www.kkkk1000.com/images/getImgData/arithmetic.gif'.'https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be40ccc434be0~tplv-t2oaga2asx-image.image'];
function loadImg(url) {
    return new Promise((resolve, reject) = > {
        const img = new Image()
        img.onload = function () {
            console.log('One image is loaded');
            resolve();
        }
        img.onerror = reject
        img.src = url
    })
};

function limitLoad(urls, handler, limit) {
    // Make a copy of the array
    const sequence = [].concat(urls)
    let promises = [];

    // Maximum number of concurrent requests
    promises = sequence.splice(0, limit).map((url, index) = > {
        // The index returned here is the script for promises, which is used to find the completed script after promise.race
        return handler(url).then((a)= > {
            return index
        }); 
    });

    // Use the array reduce method to execute as a queue
    return sequence.reduce((last, url, currentIndex) = > {
        return last.then((a)= > {
            // Return the Promise with the fastest state change
            return Promise.race(promises)
        }).catch(err= > {
            // Catch is not only used to catch errors thrown by previous THEN methods
            // More importantly, to prevent the entire chain call from breaking
            console.error(err)
        }).then((res) = > {
            // Replace the fastest-changing Promise with a new Promise
            promises[res] = handler(sequence[currentIndex]).then((a)= > { returnres }); })},Promise.resolve()).then((a)= > {
        return Promise.all(promises)
    })

}
limitLoad(urls, loadImg, 3)

/* The limitLoad function also returns a Promise, so when all images are loaded, LimitLoad (urls, loadImg, 3). Then (() => {console.log(' all images are loaded '); }).catch(err => { console.error(err); }) * /
Copy the code

conclusion

These questions, there is the examination of Promise basic knowledge, there is also the flexible use of Promise, if these questions you do very well, then your understanding of Promise should be good.

Finally, if there are shortcomings or mistakes in the article, please also point out small friends, thank you very much. If you feel that the content of the article is not enough, finally there are articles related to the topic, you can have a look.

reference

Getting started with ECMAScript 6 — Yifeng Ruan

Let’s talk about Promise

An interview question about the Promise application

Ali front-end test — understanding and application of the Promise function in ES6

This time, thoroughly understand the JavaScript execution mechanism

A Promise interview question

Introduction to all methods of ES6 Native Promise (with an application Scenario topic)

Promise asynchronous process control