Learning Silicon Valley ---- Promise notes

With regard to asynchronous processing, the callback of ES5 makes us fall into hell, the Promise of ES6 makes us get rid of the magic barrier, and finally the async await of ES7 leads us to the light.

The callback function in es5 refers to a function passed as a parameter to another function. The function as a parameter is a callback function.

Promises object is a specification proposed by CommonJS working group, which aims to provide a unified interface for asynchronous programming.

In short, its idea is that each asynchronous task returns a Promise object, which has a then method that allows you to specify a callback function. For example, the callback function f2 of f1 can be written as:

f1().then(f2);

Asynchronous programming

fs file operation

require ('fs').readFile('./index.html', (err,data) => {})

Ajax

$.get('/server', (data) => {})

timer

setTimeout(() => {}, 2000)

The above content uses pure callback function to perform asynchronous operation

Promise is a new solution for es6 introducing asynchronous programming

Syntax: a constructor. You can instantiate objects, encapsulate asynchronous operations, and obtain successful and failed results

Why use Promise?

1) More flexible way to specify callback function

Old: must be specified before starting an asynchronous task

After the "promise" function is bound to multiple tasks asynchronously, the "promise" function can even return to the "promise" function

2) Support chain call, which can solve the problem of callback hell

asyncFunc1(opt, (...args1) => {
	asyncFunc2(opt, (...args2) => {
		asyncFunc3(opt, (...args3) => {
			asyncFunc4(opt, (...args4) => {
				//some operation
			})
		})
	})
})

Callback Hell: callback functions are nested calls. The result of asynchronous execution of external callback functions is the condition for the execution of nested callbacks

Disadvantages of callback Hell: it is not easy to read and handle exceptions

Case requirement 1: click the lucky draw button and wait for 2 seconds to inform whether you have won the prize. The probability of winning the prize is positioned at 30%. A pop-up box will be displayed for winning the prize, "Congratulations, you have won the prize". If you have not won the prize, a pop-up box "keep working hard" will pop up

Case requirement 2: promise implements Ajax request

Case requirement 3: promise encapsulates Ajax requests

promise status

An attribute [PromiseState] in the instance object is built-in, and we cannot operate it directly

*Pending pending

*Resolved / fully successful

*rejected failed

State change of promise

1.pending ===> resolved

2.pending ===>rejected

Note: there are only two kinds, and a Promise object can only be changed once

Whether it turns into success or failure, there will be a result data

The successful result data is generally called value, and the failed result data is generally called reason

Value of promise object

Another attribute in the sample object [PromiseResult]

Saves the results of asynchronous tasks [success / failure]

The resolve and reject functions can modify this property

Basic process of promise

[the external chain image transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-raabrfsr-1607945193404) (C: \ users \ Sundan \ appdata \ roaming \ typora user images \ image-20201205190541879. PNG)]

How to use promise

1.Promise constructor: Promise (executor) {}

(1) executor function: resolve, reject = > {} / / arrow function or anonymous function can be used

(2) resolve function: the function we call when the internal definition is successful value = > {}

(3) reject function: the function we call when the internal definition fails reason = > {}

Note: the executor function will be called synchronously within promise immediately, and the asynchronous operation will be executed in the executor

let p = new Promise((resovle, reject) => {
    console.log(11111)
})
console.log(22222)

2.Promise.prototype.then method: (onresolved, onrejected) = > {} / / used to specify callback

(1) onResolved function: successful callback function (value) = > {}

(2) onRejected function: failed callback function (reason) = > {}

Note: specify the success callback used to get the success value and the failure callback used to get the failure reason

Returns a new Promise object

3.Promise.prototype.catch method: (onrejected) = > {}

(1) onRejected function: failed callback function (reason) = > {}

let p = new Promise((resovle, reject) => {
    //Modify promise status
    reject('error')
})
p.catch(reason => {
    console.log(reason)
})

4.Promise.prototype.finally method: () = > {}

The callback function of the finally() method does not accept any parameters. Regardless of the final state of promise, the callback function specified by the finally method will be executed after the callback function specified by then or catch is executed

5.Promise.resolve() method (value) = > {}

(1) value: successful data or promise object

Description: return a success / failure promise object (you can quickly get a promise object / encapsulate a value and convert this value into a promise object)

let p1 = Promise.resolve(521)
console.log(p1)
//If the passed in parameter is an object of non Promise type, the result returned is success
//If the passed in parameter is Promise object, the result of the parameter determines the result of resolve
let p2 = Promise.resolve(new Promise((resolve, reject) => {
    // resolve('ok')
    reject('error')
}))
p2.catch(reason => {
    console.log(reason)
})

6.Promise.reject() method (reason) = > {}

(1) Reason: the reason for the failure

Description: returns a failed promise object

let p3 = Promise.reject(521)
console.log(p3)
let p4 = Promise.reject(new Promise((resolve, reject) => {
    resolve('ok')
}))
console.log(p4)

7.Promise.all() method (promise) = > {}

(1) promise: an array containing n promises

Note: return a new promise. Only when all promises are successful can they succeed. As long as one fails, it will fail directly

let p1 = new Promise(((resolve, reject) => {
    resolve('ok')
}))
// let p2 = Promise.resolve('success')
let p2 = Promise.reject('error')
let p3 = Promise.resolve('successful')
const result = Promise.all([p1,p2,p3])
console.log(result)

8.Promise.race() method (promises) = > {}

(1) promise: an array containing n promises

Note: return a new promise. The result state of the first completed promise is the final result state

let p1 = new Promise((resolve, reject) => {
    // resolve('ok')
    setTimeout(() => {
        resolve('ok')
    },1000)
})
let p2 = Promise.resolve('success')
let p3 = Promise.resolve('successful')
const result = Promise.race([p1,p2,p3])
console.log(result)

How Promise object state changes

let p = new Promise((resolve, reject) => {
    //1.resolve function
    //resolve('ok')  //pending ===> fulfilled(resolved)
    //2.reject function
    //reject('error')  //pending ===> rejected
    //3. Throw an error
    throw 'Something's wrong'
})
console.log(p)

A Promise specifies multiple success / failure callback functions, which will be called when changing to the corresponding state

Change Promise state and specify callback function who comes first and who comes later

(1) It is possible to specify the callback first and then change the state, but you can also change the state first and then specify the callback

(2) How to change the state first in the specified callback?

1) directly call resolve/reject in the actuator

2) call then() after a longer delay

(3) When can I get the data?

1) if the callback is specified first, when the state changes, the callback function will be called to get the data

2) if the state is changed first, when the callback is specified, the callback function will be called to get the data

Promise. What determines the result status of the new promise returned by then?

let p = new Promise((resolve, reject) => {
    resolve('ok')
})
let result = p.then(value => {
    //console.log(value)
    //1. Throw an error
    //throw 'except problem'
    //2. The returned result is an object of non Promise type
    // return 521
    // 3. The returned result is Promise object
    return new Promise((resolve,reject) => {
        // resolve('success')
        reject('error')
    })

}, reason => {
    console.warn(reason)
})
console.log(result)

Concatenate multiple tasks

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok')
    },1000)
})
p.then(value => {
    return new Promise((resolve, reject) => {
        resolve('success')
    })
}).then(value => {
    console.log(value)
}).then(value => {
    console.log(value)
})

extraordinary transmission

You can only specify the failed callback, and there is no need to specify the failed callback elsewhere

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok')
        // reject('error')
    },1000)
})
p.then(value => {
    throw 'Error '
//    console.log(111)
}).then(value => {
    console.log(222)
}).then(value => {
    console.log(333)
}).catch(reason => {
    console.warn(reason)
})

Interrupt Promise chain

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok')
        // reject('error')
    },1000)
})
p.then(value => {
   console.log(111)
   //There is only one way
   return new Promise(() => {}) //The promise in pending state is unchanged from the promise state above, so the subsequent callback function will not be executed
}).then(value => {
    console.log(222)
}).then(value => {
    console.log(333)
}).catch(reason => {
    console.warn(reason)
})

Custom Promise

Disadvantages of promise

1. Promise cannot be cancelled. Once it is created, it will be executed immediately. It cannot be cancelled halfway.

2. If the callback function is not set, the error thrown by promise will not be reflected to the outside.

3. When it is in the pending state, it is impossible to know which stage it has reached (just started or about to be completed).

Advantages of promis

1. Solve the Callback Hell problem

2. Better error capture
In addition to the code indentation problem mentioned above, multiple nested callback s may cause the inability to capture exceptions or uncontrollable exception capture.

1) For example, in the following code, we use setTimeout to simulate asynchronous operation, in which an exception is thrown. However, in the asynchronous callback, the execution stack of the callback function is separated from the original function, resulting in the external failure to catch the exception.

function fetch(callback) {
    setTimeout(() => {
        throw Error('request was aborted')
    }, 2000)
}

try {
    fetch(() => {
        console.log('Request processing') // Never execute
    })
} catch (error) {
    console.log('Trigger exception', error) // Never execute
}

// Program crash
// Uncaught Error: the request failed

(2) If you use projects, set the state of the project to rejected through the reject method, so that we can catch it in then, and then execute the callback of "failure".

function fetch(callback) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
             reject('request was aborted');
        }, 2000)
    })
}


fetch()
.then(
    function(data){
        console.log('Request processing');
        console.log(data);
    },
    function(reason, data){
        console.log('Trigger exception');
        console.log(reason);
    }
);

async await is the syntax sugar of promise and generator

async and await

async function

(1) The return value of the function is promise object

(2) The result of the promise object is determined by the return value of the async function

//The return rule is the same as that of the then method
async function main(){
    //1. If a non Promise type data is returned
    // return 521
    //2. If a Promise object is returned
    // return new Promise((resolve, reject) => {
    //     // resolve('ok')
    //     reject('Error')
    // })
    //3. Throw an exception
    throw "oh no"
}
let result = main()
console.log(result)

await expression

(1) The expression on the right side of await is generally Promise object, but it can also be other values

(2) If the expression is a promise object, await returns the value of promise success

(3) If the expression is another value, this value is directly used as the return value of await

be careful:

(1) Await must be written in async function, but there can be no await in async function

(2) If the promise of await fails, an exception will be thrown, which needs to be captured and processed through try... catch

Case: if there are three requests to occur, the third request depends on the result of the second request, and the second request depends on the result of the first request. If implemented with ES5, there will be three layers of callbacks. If implemented with Promise, at least three then are required. One is the horizontal development of the code, and the other is the vertical development. If async and await are used

//We still use setTimeout to simulate asynchronous requests
function sleep(second, param) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(param);
        }, second);
    })
}

async function test() {
    let result1 = await sleep(2000, 'req01');
    let result2 = await sleep(1000, 'req02' + result1);
    let result3 = await sleep(500, 'req03' + result2);
    console.log(`
        ${result3}
        ${result2}
        ${result1}
    `);
}

test();
//req03req02req01
//req02req01
//req01

Execution sequence:

(1) await expression will pause the execution of current async function and wait for Promise processing to complete;

(2) If Promise is handled normally (Resolved, also known as Fulfilled), the parameter of the callback resolve function is used as the value of await expression to continue to execute async function;

(3) If the Promise handles the rejected exception, the await expression will throw out the reason of the Promise exception;

Tags: Javascript ECMAScript

Posted by vividona on Mon, 02 May 2022 19:23:51 +0300