Promise object, solve callback hell, and execute code synchronously
This article records the knowledge points studied
BY: Lin Yi
preface:
-
Asynchronous operation is an advantage of JS and brings great trouble. There is a word called callback hell, that is, in a callback function, execute another asynchronous task and nest it all the time, resulting in poor readability and inconvenient maintenance
-
Promise is a new solution in ES6 to solve callback problems
-
Promise enables asynchronous code to be executed synchronously
-
Asynchronous tasks include: events, timers, Ajax requests, file operations, and database operations. Asynchronous tasks can only receive results from callback functions
// Callback hell, case // When asynchronous operations return results is uncontrollable. If they are requested in order, they can only be nested $.get(url,function(res){ $.get(url,function(res){ $.get(url,function(res){ console.log(res); // Get the final result }) }) }) // The following is the callback hell solution case code
introduce
-
Promise is a solution to asynchronous programming. From the perspective of syntax, it is an object and needs new when used
-
Promise can be understood as a container in which asynchronous code can be written.
-
Like other new objects, new Promise is a synchronization task.
-
When the result is obtained, it is asynchronous to call resolve to trigger the then method. The successful result is given to resolve and the failure is given to reject
Creating Promise objects and using
// Create Promise object // The incoming function will be executed automatically and immediately, which belongs to the synchronization task let p = new Promise(function (resolve, reject) { $.ajax({ url: 'http://123.57.109.30:3000/api/categoryFirst', success(res) { resolve(res); //The resolve method was called successfully }, error(err) { reject(err); //Failed to call reject method } }) }) // Call mode 1 p.then(function (res) { console.log(res); // Get successful results }).catch(function (err) { console.log(err); // Result of failure }) // Call mode 2 p.then(Successful callback function, Failed callback function); p.then(function(res){}, function(err){}); //grammar
Three states of Promise
The state of the object is not affected by the outside world. The promise object returned represents an asynchronous operation. There are three states
Once the state changes, it will not change again. This result can be obtained at any time
// Encapsulate function and return Promise object function myAjax(url) { return new Promise(function (resolve, reject) { $.ajax({ url: url,success(res){ resolve(res) }, error(err){ reject(err) }}) }) } let p = myAjax("http://xxx.com/api/getbook"); console.log(p); // The obtained Promise object represents the asynchronous operation state // Pending, the Promise result is undefined // Resolved (completed, also known as completed). At this time, the Promise result is the value passed to the resolve function // Rejected (failed). At this point, the result of Promise is the value passed to the reject function
In the then() method, the non Promise object value is returned, and the value is directly used in the next then
// In the then() method, the non Promise object value is returned, and the value is directly used in the next then // If a Promise object is returned, it will replace the Promise object returned by then by default let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('1 Execution completed in seconds') }, 1000); }) // After then is executed, a new Promise object will be obtained, and the new Promise object stored in newP is the new Promise object let newP = p.then(res => { console.log(res); // completion of enforcement return 1212; // Return to the next Promise object and print "1 second execution completed" }) // call chaining newP.then(function (res) { console.log(res); // Get the return value of the previous Promise object and print 1212 })
Callback scheme 1
// If a Promise object is returned, it will replace the new Promise object returned in place by then function myAjax(url) { // Encapsulate function and return Promise object return new Promise(function (resolve, reject) { $.ajax({ url: url, success(res){ resolve(res) }, error(err){ reject(err) } }) }) } //-----------------------The following code can also omit the receiving step and write it in a direct chain // Get level 1 Classification Data let p = myAjax('http://123.57.109.30:3000/api/categoryFirst'); // Return Promise object let newP = p.then(function(res){ console.log(res); // Get the data of level 1 Classification // Get level 2 classification data and return Promise object return myAjax('http://123.57.109.30:3000/api/categorySecond?firstId=' + res.list[8].firstId); }) let newPP = newP.then(function(res){ console.log(res); // Get the data of level 2 classification // Get level 3 Classification and return Promise object return myAjax('http://123.57.109.30:3000/api/categoryThird?secondId=' + res.list[2].secondId); }) newPP.then(function(res){ console.log(res); // Get the data of level 3 classification })
async and await
async and await were proposed in ES2017. Their appearance simplifies the use of Promise
async is used to modify a function. The modified function always returns a Promise object
await can only appear in async modified functions. await will wait until the result is returned. Otherwise, it will wait forever, but it will not affect the code outside the function body.
Final solution
// The use of async and await is the ultimate perfect solution async function getAjax(){ // To obtain level 1 classification data, the myAjax method is the same as that in scheme 1 above let res = await myAjax('http://123.57.109.30:3000/api/categoryFirst'); // Get level 2 classification data res = await myAjax('http://123.57.109.30:3000/api/categorySecond?firstId=' + res.list[8].firstId); // Get level 3 Classification res = await myAjax('http://123.57.109.30:3000/api/categoryThird?secondId=' + res.list[2].secondId); console.log(res); // Get the final result } getAjax(); // Call the function identified by async