ES: Summary of some knowledge of callback function, Promise, async/await (If you encounter problems in the future, it will be updated at any time)

Tell interesting knowledge in your own words.


Hi everyone, I am 梅巴哥er. This article talks about some callback functions and promise-related knowledge.
Knowledge about promises will be updated in this blog in the future. The explanations involved are all personal understandings. If there is any inappropriateness, you are welcome to point it out in the comment area. Will reply and correct in time.


Reference

Speaking of promises, we have to talk about callback functions first.

What is a callback function
  • As the name implies, it is a function called (execute other code first, and then) call back.
// 先看个栗子
function a(m) {
    
    
    console.log(m)
}
function b(callback) {
    
    
    var n = 1
    callback(n)
}
b(a) // 输出 1
// 可以看出:
// 回调函数a被当做实参传入函数b
// 在执行函数b时,回调函数a被调用

The last chestnut is a synchronously executed function, that is, when a is called by b, it is executed immediately
without waiting.

// 那么,我们再来看个栗子
function callback() {
    
    
	console.log(1)
}
setTimeout(callback, 1000)
// 先执行外层的setTimeout函数,然后调用callback函数。
// 这里的callback就是一个回调函数。
// 回调函数在另一个函数里充当参数

Obviously, this chestnut is an asynchronous callback, and it needs to wait before executing the callback function.
In other words, the execution of the callback function can be synchronous or asynchronous.

In practical applications, the most common ones are in asynchronous applications.


What's the use of callback function

As can be seen from the above example,

  • The callback function is executed both synchronously and asynchronously
  • When executing asynchronously, the execution channel will not be blocked. (Is it very polite to let others execute it first and then execute it asynchronously?)
  • Can optimize loading performance, such as lazy loading of pictures.

What about callback hell?

Let's first look at an example:

function a(num, callback) {
    
     
    setTimeout(() => {
    
    
        console.log(num)
        callback() // 回调函数
    }, 1000)
}
a(1, function () {
    
     // 无限调用
    a(2, function() {
    
    
        a(3, function () {
    
    
            a(4, function () {
    
    
                a(5, function () {
    
    
                    console.log('多少层了')
                })
            })
        })
    })
})
// 可以无限写下去。。

As can be seen from the above example,

  • The function has been calling the callback function until the Nth level.
  • It's too complicated, and it's easy to get dizzy if you watch too much.
  • It is not convenient to modify and maintain the code.
  • When the callback function is complicated, the sense of hierarchy is poor, and you may not understand what you wrote after a while.

There is an old saying in China that if someone does a heinous thing, he will be sent to the 18th hell!

Look at the function of the chestnut above, go down layer by layer, does it look like hell? ? ?

So, this kind of callback is called 回调地狱!

However, in our usual applications, we often need to call asynchronously and even call dolls. What should we do?


ES6's promise solves callback hell

Now, let's modify the above code:

function a(num) {
    
    
    return new Promise((resolve, reject) => {
    
    
        setTimeout(() => {
    
    
            console.log(num)
            resolve() // 状态成功,执行then里面的函数
            // reject() // 状态失败,执行catch里面的函数
        }, 1000)
    })
}
a(1)
.then(() => a(2)) // then函数里返回的仍然是一个promise对象
.then(() => a(3))
.then(() => a(4))
.then(() => a(5))
.then(() => console.log('多少层了'))
.catch(error => console.log(error))
// resolve取代了回调函数
// 当状态成功时,then指向的是回调函数,一个新的promise对象

Look at it now, isn't it clearer?
You look at the layer by layer, it's very clear and beautiful, and it looks like a pie, and you drool when you look at it... It's so fragrant!


Questions raised by examples

Looking at the chestnuts above, do you want to ask:
What does this mean?
What is that promise?
Why are there a bunch of .then() for?
How can resolve and reject still have status?
Why does it suddenly become clear after using promises?


Start Promise是什么talking about

From the above example, it is not difficult to see:

  • A promise is an object returned by a function
// 如上面的栗子
function a(num) {
    
    
	return new Promise((resolve, reject) => {
    
    
		...
	}
}
// 函数a返回(return)了一个对象new Promise()
// 以后我们想用Promise了,就返回或声明一个Promise即可
// Promise通过.then绑定了回调函数(then里面就是回调函数了)
// resolve状态下,执行了then里面的回调函数
// 和回调地狱里的栗子a(num, callback){...}相比,
// Promise栗子的a函数的形参里,
// 并没有写callback回调函数了,因为回调函数已经通过promise绑定了
// .then可以添加多个,按照顺序依次执行,直至回调结束
// 这种多个then(和.catch)的形式,叫链式调用

Let's look at another chestnut:

let promise = new Promise((resolve, reject) => {
    
    
        console.log(1)
        // resolve() // 这个状态才会执行then
        reject() // 这个状态才会执行catch
        // catch后的then,不管什么状态,都会执行
    })
       
promise
.then(() => console.log(2))
.catch(() => console.log(3))
.then(() => console.log(4))
// 输出:1 3 4
// 可以看出:
// 当状态是reject时,会执行.catch里的函数。
// .catch前的.then不会执行
// 而.catch后面的.then不受影响,会继续执行

What does the status success and failure mentioned above mean?

This is just a personal expression habit.
In fact, this is also talking about the state of Promise.

Promise has three states and must be in one of them:

  • Pending: The initial state, neither being honored nor rejected.
  • Fulfilled: means the operation completed successfully.
  • Rejected (rejected): Means the operation failed.

When the operation is successful (the asynchronous task is successfully completed and the result value is returned):
the callback function of .then will be executed (that is, the resolve function is called)

When the operation fails (asynchronous task fails and the reason for the failure is returned): the
.catch function will be executed (that is, the reject function is called)


Give two chestnuts to deepen understanding
// example1
let pro = new Promise((resolve, reject) => {
    
    
    setTimeout(
        () => resolve('成功') // 异步代码执行成功,调用resolve函数
    , 1000)
})
pro
.then(message => console.log('good!' + message + '了!'))
// message的值,是上面调用resolve(..)函数传入的值
// 相当于这样:
// function resolve(message) {console.log('good!' + message + '了!')}
// 这个值不一定是字符串,还可以是别的。
// 比如 resolve(data)

// example2
let pro = new Promise((resolve, reject) => {
    
    
    setTimeout(
        () => reject('failed...') // 异步代码执行失败,调用reject函数
    , 1000)
})
pro
.then(message => console.log('good!' + message + '了!'))
.catch(error => console.log(error))
.then(() => console.log('end!'))
// 输出:
// failed...   end!
// reject('failed...')就相当于:
// function reject(error) {console.log(error)} 
// 再调用reject函数: reject('failed...')

Talk about async/await

Now that we talked about ES6's Promise, we have to mention ES7's async/await. Because async came about to simplify Promise.

In order to better understand, I now modify the example1 code of the Promise example:

// example1改造后
let pro= () => new Promise((resolve, reject) => {
    
    
    setTimeout(
        () => resolve('成功') // 异步代码执行成功,调用resolve函数
    , 1000)
})

async function asyncExample() {
    
    
    console.log(1)
    const result = await pro()
    console.log(result)
}
asyncExample()
// 输出: 1 成功

Comparing the code before and after the transformation, the problem appeared
  • Where did the .then before the transformation go?
  • Before the let pro = new Promise(..)transformation, how did it become after the transformation let pro= () => new Promise(..)?
  • After the transformation, it looks more concise, and it looks like it has become a synchronous code. Is there anything special about async/await?

Problem analysis and async explanation

From the modification of the example, we can know:

  • async is a declarative function, that is, async is added before the ordinary function.async function pro(){..}
  • Async/await often occur at the same time, but it is not necessary. Await can be 0 or N multiple.
  • Await is followed by a Promise function, such asawait pro()
  • What await pro() generates is a promise object. For example const result = await pro(), the result here is a promise object
  • await must be placed inside the async function before it can be executed. Put it outside to report an error.
  • The async function must return a promise object
  • await pro()Is equivalent to.then((param) => {return param})

The relationship and difference between promse and async
  • Most async functions can also be written using Promises
  • In terms of error handling, the async function is easier to catch abnormal errors
  • The async function is modified on the basis of the Promise function
  • async will return a promise object that stores the data
  • async can get data more intuitively

the above.

Guess you like

Origin blog.csdn.net/tuzi007a/article/details/114442593