Hi I'm Shendi
Detailed explanation of Promise in JS, elegant writing of asynchronous tasks
Promise is a class provided by ECMAScript 6, a new addition to ES6, the purpose is to write complex asynchronous tasks more elegantly
Most browsers support it, some older browsers don't
Introduction
In the browser, the running of the program is synchronous (single-threaded). To achieve asynchrony, you can use the setTimeout function, and AJAX can also be executed asynchronously.
When the requirements are very complicated, for example, to create an animation effect, move the element up by 50 pixels within two seconds, and then move to the left by 10 pixels within one second, the code is as follows
var ele = document.getElementById("id");
// 计算一次多少毫秒,两秒50,一秒10
var oneNum = 2000/50, twoNum = 1000/10;
var num = 0, num2 = 0;
// 两秒移动50像素
function animOne() {
setTimeout(function () {
ele.style.top -= 1;
num++;
if (num == oneNum) {
animTwo();
} else {
anim();
}
}, oneNum);
}
// 一秒往左移动10像素
function animTwo() {
setTimeout(function () {
ele.style.left -= 1;
num2++;
if (num2 == twoNum) {
// 动画完成
} else {
animTwo();
}
}, twoNum);
}
animOne();
The above code does not seem to be a big problem, but if the requirements change and move down on the previous basis, you need to call animThree (move down) after the execution of animTwo is completed. If the requirements change again, add more operations
Our solution is probably to change the form of directly specifying the function call after the operation is completed to pass the callback parameter call, for example
// 两秒移动50像素
function animOne(callback) {
setTimeout(function () {
ele.style.top -= 1;
num++;
if (num == oneNum) {
if (callback) callback();
} else {
anim();
}
}, oneNum);
}
// 一秒往左移动10像素
function animTwo(callback) {
setTimeout(function () {
ele.style.left -= 1;
num2++;
if (num2 == twoNum) {
if (callback) callback();
} else {
animTwo();
}
}, twoNum);
}
function animThree() {
...}
animOne(animTwo(animThree));
This method of asynchronous callback can be replaced by Promise, the purpose is to write complex asynchronous tasks more elegantly
can be understood as a norm
Advantage
more flexible
In the traditional callback, the callback function needs to be passed when calling, for example
animOne(aniTwo());
In Promise, it can be specified at any time (it can also be called after asynchronous execution is completed)
Support chain calls to solve callback hell
Callback hell refers to a situation where the nesting of callback methods is used excessively, making the code look very deep, difficult to maintain and understand. Here is an example:
function getDataFromServer(url, callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4 && httpRequest.status === 200) {
var responseData = JSON.parse(httpRequest.responseText);
callback(responseData);
}
};
httpRequest.open('GET', url, true);
httpRequest.send();
}
getDataFromServer('https://example.com/data1', function(response1) {
getDataFromServer('https://example.com/data2/' + response1.id, function(response2) {
getDataFromServer('https://example.com/data3/' + response2.id, function(response3) {
// do something with the data
});
});
});
In the example above, the three nested callbacks can get very deep, making the code difficult to understand and maintain. To solve the callback hell problem, techniques such as Promise or async/await can be used.
Promise
Create an object through new Promise. The constructor has one parameter, which is a function. This function also has two parameters, usually named resolve and reject, which are also functions
Among them, when the function is successfully executed, resolve should be called, and reject should be called when the execution fails. You can define the parameters of these two functions by yourself
For example
var p = new Promise(function (resolve, reject) {
if (true) {
// 成功
resolve("成功了");
} else {
// 失败
reject("失败了");
}
});
resolve and reject can be understood as callback functions
Promise itself is not asynchronous, but used to contain the execution of asynchronous operations
The function passed by creating a Promise will be executed directly (synchronously)
The Promise object has the following functions
name | describe |
---|---|
then | The function will be executed after success and return the promise object |
catch | Function, which will be executed after failure and returns promise object |
finally | Function, execute regardless of success or failure, return promise object |
For example
p.then(function (val) {
console.log(val);
}).catch(function (val) {
console.log(val);
});
three states
The three states of Promise are:
- Pending (in progress): The Promise object is in the Pending state when it is created, indicating that the asynchronous operation is in progress and has not yet been completed.
- Fulfilled (completed): The asynchronous operation is successfully completed, the Promise object changes from the Pending state to the Fulfilled state, and a result value is returned at the same time.
- Rejected (failed): An error or exception occurs in the asynchronous operation, the Promise object changes from the Pending state to the Rejected state, and an error message is returned at the same time.
In the life cycle of Promise, the status will only change from Pending to Fulfilled or Rejected. Once the state transitions to Fulfilled or Rejected, it remains unchanged until the Promise object is released.
When the state changes to Fulfilled or Rejected, the corresponding callback function will be executed, and how many are executed, for example
p.then(function () {
console.log(1);
}).then(function () {
console.log(2);
}).then(function () {
console.log(3);
});
Output 123 will be executed in sequence
If the catch chain is called, only the first one will be executed
Chain calls are executed in sequence, then can pass function parameters, and any exceptions in then will be directly executed catch
var p = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(1);
resolve(2);
}, 2000);
});
p.then(function (val) {
console.log(val);
return 3;
}).then(function (val) {
console.log(val);
}).finally(function () {
console.log("end");
}).then(function (val) {
console.log(val);
throw "4 error";
}).catch(function (val) {
console.log(val);
});
async function
Async function is a specification of ECMAScript 2017 (ECMA-262) standard, which is supported by almost all browsers except Internet Explorer.
An asynchronous function is a type of JavaScript function that allows the execution of code not to block during execution, but to continue other operations in the background. Asynchronous functions typically use methods such as callbacks, Promises, or async/await to handle asynchronous operations.
Adding a modifier before the function async
represents an asynchronous function, and the asynchronous function is executed asynchronously as a whole
In an asynchronous function, await can be used to wait for the promise result, for example
function showText(text, delay) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(text);
resolve();
}, delay);
});
}
async function test() {
await showText("一秒过去了", 1000);
await showText("两秒过去了", 1000);
await showText("五秒过去了", 3000);
}
test();
The principle is exactly the same as the Promise native API mechanism, but it is easier for programmers to read
In the asynchronous function, you need to use try catch to catch the exception
If the promise has a normal return value, it can be assigned directly
async function test() {
try {
await new Promise(function (resolve, reject) {
reject("错误");
// 或者抛出错误
// throw "错误";
});
} catch (e) {
console.log(e); }
await new Promise(function (resolve, reject) {
resolve("返回值");
});
}
END