The Promise object in JS solves the detailed explanation of callback hell cases and allows the code to execute synchronously

Keywords: Javascript Front-end ECMAScript

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

Posted by nivosh on Sat, 06 Nov 2021 06:57:02 -0700