Topic 1
const promise = new Promise((resolve, reject) => { console.log(1); resolve(); console.log(2); }) promise.then(() => { console.log(3); }) console.log(4);
analysis
First, Promise will be executed immediately after it is created, so 1 and 2 will be output first, and {Promise The code inside then () executes immediately at the end of the event loop, so it will continue to output 4 and finally output 3.
answer
1 2 4 3
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); })
analysis
The resolve function changes the state of the Promise object from "incomplete" to "successful" (that is, from "pending" to "resolved"), which is called when the asynchronous operation is successful, and passes the result of the asynchronous operation as a parameter;
The reject function changes the state of the Promise object from incomplete to failed (that is, from pending to rejected). It is called when the asynchronous operation fails, and passes the error reported by the asynchronous operation as a parameter.
Once the state changes, it will not change again.
So reject('error ') in the code; It won't work.
Promise can only resolve once, and the remaining calls will be ignored.
So the second time is "resolve('success2 '); It won't work.
answer
then: success1
Topic 3
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log)
analysis
Promise. If the parameter of the resolve # method is an original value or an object without the # method, then # promise The resolve # method returns a new # promise # object with the status of resolved, promise The parameters of the resolve} method will be passed to the callback function at the same time.
The parameter accepted by the then , method is a function. If it is not a function, it will actually interpret it as , then(null), which will cause the result of the previous , Promise , to penetrate below.
answer
1
Topic 4
The red light is on once every three seconds, the green light is on once every second, and the yellow light is on once every two seconds; How to make the three lights turn on alternately and repeatedly? Promse has three functions:
function red() { console.log('red'); } function green() { console.log('green'); } function yellow() { console.log('yellow'); }
analysis
The red light is on once every three seconds, the green light is on once every two seconds, and the yellow light is on once every two seconds, which means that the red function is executed once in three seconds, the Yellow function is executed once in two seconds, and the Green function is executed once in one second, and the Green function is executed repeatedly, which means that the Green function is executed after one second, the Yellow function is executed after one second, the red function is executed after one second, and the process is repeated. The code is as follows.
answer
function red() { // 3 Once per second console.log('red'); } function green() { // 1 Once per second console.log('green'); } function yellow() { // 2 Once per second console.log('yellow'); } async function light(duration,cb) { return new Promise((resolve,reject) => { setTimeout(() => { cb(); resolve(); },duration); }) } async function step() { while(true) { await light(1000,green); await light(1000,yellow); await light(1000,red); } } step();
In extending an example: we now want to implement a traffic light, and change the background color of a circular div according to the cycle of green for 3 seconds, yellow for 1 second and red for 2 seconds.
(function (){ var btn = document.getElementById('status'); function sleep(duration){ return new Promise(function(resolve,reject){ setTimeout(resolve,duration); }) } async function changeColor(duration,color){ btn.style.background = color; await sleep(duration); }; async function fn(){ while(true){ await changeColor(3000,'green'); await changeColor(1000,'yellow'); await changeColor(2000,'red'); } } fn(); })();
Topic 5
Implement the mergePromise function, execute the passed in array in sequence, and put the returned data into the array data in sequence.
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 => { // Implement your code here }; mergePromise([ajax1, ajax2, ajax3]).then(data => { console.log('done'); console.log(data); // data by [1, 2, 3] }); // Separate output is required // 1 // 2 // 3 // done // [1, 2, 3]
analysis
First of all, ajax1, ajax2 and ajax3 are all functions, but they will return a "Promise" after execution. According to the requirements of the topic, we just need to execute the three functions in sequence, and then put the results into "data", but these functions are asynchronous operations. It is not so simple to execute them in sequence and then output 1, 2 and 3. Let's see an example.
function A() { setTimeout(function () { console.log('a'); }, 3000); } function B() { setTimeout(function () { console.log('b'); }, 1000); } A(); B(); // b // a
In the example, we execute # a, B # in order, but the output is # B, a # for these asynchronous functions, we will not execute one in order and then the next.
This question is to use Promise to control asynchronous processes. We need to find a way to make these functions execute one after the other. Let's see the answer.
answer
// Save the result after the function in the array is executed var data = []; // Promise.resolve Method calls without parameters and returns a resolved Stateful Promise Object. var sequence = Promise.resolve(); ajaxArray.forEach(function (item) { // First time then Method is used to execute each function in the array, // Second time then Method accepts the result returned after the function in the array is executed, // And add the results to data In the middle, and then put data return. // Right here sequence The reassignment of is actually equivalent to an extension Promise chain sequence = sequence.then(item).then(function (res) { data.push(res); return data; }); }) // After traversal, a Promise,that is sequence, His [[PromiseValue]] Value is data, // and data(Save the result of the function execution in the array) will also be passed into the next call as a parameter then Method. return sequence;
Topic 6
What is the final output of the following code?
const first = () => (new Promise((resolve, reject) => { console.log(3); let p = new Promise((resolve, reject) => { console.log(7); setTimeout(() => { 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);
analysis
In fact, this problem has little to do with "Promise". The main reason is that we need to understand the JS execution mechanism in order to solve this problem well. Friends who do not understand the JS execution mechanism are recommended to take a look at this article
This time, thoroughly understand the JavaScript execution mechanism
First event cycle
Execute the macro task first, execute the main script and new Promise immediately, and output [3],
Execute p this new Promise operation and output [7],
Find setTimeout, put the callback into the next round of task queue (Event Queue), then of p, temporarily called then1, into the micro task queue, and then of the first, called then2, into the micro task queue. Execute console Log (4), output [4], and the macro task is finished.
Then execute the micro task, execute then1, and output [1],
Execute then2 and output [2].
So far, the first round of event cycle ends. Start the second round.
Second event cycle
First execute the callback in the macro task, that is, setTimeout, and output [5].
resolve(6) will not take effect because p the Promise state will not change once it is changed.
answer
3 7 4 1 2 5
Title VII
There are 8 urls of image resources, which have been stored in the array "urls" (i.e. urls = ['http://example.com/1.jpg', ...., 'http://example.com/8.jpg '], and there is already a function) function loadImg. Enter a url link and return a Promise. The Promise resolve s when the picture download is completed, and reject if the download fails.
However, we require that no more than 3 links can be downloaded at any time.
Please write a piece of code to realize this requirement. It is required to download all pictures 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://www.kkkk1000.com/images/wxQrCode2.png']; function loadImg(url) { return new Promise((resolve, reject) => { const img = new Image() img.onload = function () { console.log('A picture is loaded'); resolve(); } img.onerror = reject img.src = url }) };
analysis
The meaning of the title is that we need to do this. First, we need to request three pictures concurrently. When a picture is loaded, we will continue to request one picture, keeping the number of concurrent requests at three until all the pictures to be loaded initiate requests.
To implement with Promise, first request three picture resources concurrently, so that you can get three promises to form an array, which is called promises , and then call them continuously Promise.race To return the Promise with the fastest change of state, and then delete the Promise object from the promises array, and then add a new Promise until all URLs are taken, and finally use it again Promise.all To process the promises in the array without changing the state.
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://www.kkkk1000.com/images/wxQrCode2.png']; function loadImg(url) { return new Promise((resolve, reject) => { const img = new Image() img.onload = function () { console.log('A picture 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) => { // Back here index It's the mission promises Footmark for Promise.race Then find the completed task pin return handler(url).then(() => { return index }); }); // Using array reduce Method to execute as a queue return sequence.reduce((last, url, currentIndex) => { return last.then(() => { // Returns the fastest state change Promise return Promise.race(promises) }).catch(err => { // there catch Not only to capture the front then Method // It is more important to prevent interrupting the whole chain call console.error(err) }).then((res) => { // Use new Promise Replace the fastest changing state Promise promises[res] = handler(sequence[currentIndex]).then(() => { return res }); }) }, Promise.resolve()).then(() => { return Promise.all(promises) }) } limitLoad(urls, loadImg, 3) /* Because the limitLoad function also returns a Promise, you can continue the chain call after all pictures are loaded limitLoad(urls, loadImg, 3).then(() => { console.log('All pictures are loaded '); }).catch(err => { console.error(err); }) */
Title address: Interview questions about Promise in ES6