[js] callback function callback Promise async/await

1. callback function

  • A means of encapsulating code

  • What is the concept of callback

    =>Pass function A as an argument to function B

    =>Call function A as A formal parameter inside function B

    =>We call this behavior a callback function

    =>We say that function A is the callback function of function B

function A() {
  console.log('I am A function')
}
 
function B(fn) {
  // At this time, fn parameter accepts the content inside () when written in B(): A
  // At this time, fn parameter accepts the address of global function A
  // At this time, fn parameter and global variable A operate on A function space
  console.log('I am B function')
  // Calling fn is actually calling and executing the global A function
  fn()
}

// Call B function
// A is the address of a save function
// The address of function A is passed as an argument to the fn parameter inside function B
B(A)
// Function A is the callback function of function B
  • Why do I need a callback function

  • If the code is synchronized from beginning to end, no callback function is required

    =>When you're encapsulating code

    =>And there are asynchronous times in the code

    =>And you need to do something at the end of asynchrony

    =>Using callback

Explanation: why do asynchronous end encapsulation use callback

  • Because JS is a single thread, you can only do one thing at a time

  • Main: the end time of asynchrony is uncertain

  • Example: takeout

    =>A takeout can only do one thing at a time

    =>If you want to bring an extra pair of chopsticks

    =>Scheme 1: call the takeout when he just arrives at the store

    =>Option 2: give a note when ordering

Disadvantages of callback function:
  • Callback hell

  • When callbacks are nested callbacks, the code reading and maintainability are not high

Solve the problem of callback Hell:

  • Promise to solve the callback hell

  • analysis:

    =>Promise is to solve the callback hell

    =>Callback hell is because callback functions are nested too much

    =>Callback function, in order to solve the encapsulation of doing something at the end of asynchrony

    =>Promise is an elegant scheme for asynchronous code encapsulation

// Why do I need a callback function
// Encapsulate a piece of code
// Example: what the takeout company does well
function waimai(beizhu) {

  // Get a random integer from 1000 to 6000
  const time = 1000 * Math.round(Math.random() * 5 + 1)
  console.log(' on the way ' + time)
  
  // We use setTimeout to simulate a network environment request
  setTimeout(() => {
    console.log('Arrived at the store, Get the takeout')
    // Put the code I need to execute directly in this position
    // Then this encapsulation is meaningless
    // You need to use the callback function
    // Because this position is the end of asynchrony
    // Calling beizhu from this location is called at the end of asynchrony
    // No matter when you arrive at the store
    // After you get the takeout, carry out the notes
    beizhu()
  }, time)
}

// User needs: want to take an extra pair of chopsticks
waimai(function () { console.log('Take an extra pair of chopsticks') })

// User needs: want to get more pepper
waimai(function () { console.log('Get more pepper') })

2. Callback hell

understand

  • A situation when using callback function to encapsulate code

  • Callback functions are nested inside

  • When you use a lot of code encapsulated by callback functions, there will be structural disorder

    =>It is not conducive to code reading and maintenance

  • To solve the callback hell

    =>A new syntax called Promise appears in the syntax of ES6

    =>To turn asynchronous code encapsulation into Promise syntax encapsulation

    =>Callbacks are no longer used to encapsulate asynchronous code

    =>Essence: used to encapsulate asynchronous code

Implementation requirements:

  1. Send a request, request an interface

    =>Wait until the response comes back

    =>Print content on console

  2. Send the second request and request the second interface

    =>The request must be sent again after the first request and after printing

    =>Print the response on the console

  3. Send the third request and request the third interface

    =>It is required to send the request again after the second request and after printing

    =>Print the response on the console

<script src="jquery.min.js"></script>

// Realize requirement 1:
$.ajax({
  url: 'http://localhost:8888/test/first',
  success: function (res) {
    console.log('Results of the first request')
    console.log(res)
    // When the code in this position is executed, it must be the end of the first request
    // Demand 2:
    $.ajax({
      url: 'http://localhost:8888/test/second',
      dataType: 'json',
      success: function (res) {
        console.log('Result of the second request')
        console.log(res)
        // When the code in this position is executed, it must be the end of the second request
        // Demand 3:
        $.ajax({
          url: 'http://localhost:8888/test/third',
          data: 'name=Jack&age=18',
          dataType: 'json',
          success: function (res) {
            console.log('Results of the third request')
            console.log(res)
          }
        })
      }
    })
  }
})

ajax here uses jquery

3. Know Promise

  • Is a syntax that appears in ES6

  • Promise is also a JS built-in constructor

  • promise - commitment:

    • How many committed states are there?
      =>Continue (during continuous execution)
      =>Success
      =>Fail
    • Conversion between commitment states: can only be converted once
      =>Or continue to convert to success
      =>Or continue to convert to failure
  • Promise also has three states
    =>Continue: pending
    =>Success: fulfilled
    =>Failed: rejected

const p = new Promise(function (resolve, reject) {
  // ...
  // ...
})

// Register a successful function for the current commitment
p.then(function () {
  
})

// Register a failed function for the current commitment
p.catch(function () {

})

How to change promise status

  • In the a function of new Promise
  • Two parameters are acceptable
    1. The first parameter: you can convert the Promise status from continue to success
    2. Second parameter: the Promise status can be changed from continue to fail
// 1. Asynchronous code
const p = new Promise(function (resolve, reject) {
  // resolve is a successful conversion method
  // When you write resolve(), you are converting the promise state to success
  // Will execute the b function written in. then
  // reject is a method of converting to failure
  // When you write reject(), you are converting the state of the promise to failure
  // It will execute the c function written in. catch
  // These two can only write one
 
  // Write asynchronous code that you need to encapsulate
  const time = 1000 * Math.round(Math.random() * 5 + 1)
  console.log('Promise to be together all your life')
  setTimeout(() => {
    if (time >= 3000) {
      // resolve() calls the function b inside then
      // So the time content written inside () here is the argument to b in then
      resolve(time)
    } 
    else {
      // reject() calls the catch internal function c
      // Therefore, the time content written in () here is the argument to c in catch, and it is also an error message
      reject(time)
    }
  }, time)
})

// Two methods called by promise object
// Registration succeeded
p.then(function b(t) {
  // Function b will not be called directly
  // The code in this position will be called and executed when p the promise state changes from continue to success
  console.log(t, 'Successful function b')
  // t is the content of time in the resolve parentheses written inside promise
})

// Registration failed
p.catch(function c(err) {
  // Function c is not called directly
  // The code in this position will be called and executed when p the promise state changes from continue to fail
  console.log(err, 'Failed function c')
})

4. Advanced syntax of promise

  • When a Promise is then within the code

  • As long as you return a new promise object inside the previous then with return

  • Then of the new promise object can continue writing then directly after the previous then

Requirements:

  1. Send a request for the first interface

  2. Send the second request and request the second interface
    =>Premise: you must wait until the end of the first request to send it again

function myPromiseAjax(options = {}) {
  const p = new Promise((resolve, reject) => {
    // Execute ajax
    $.ajax({
      url: options.url,
      data: options.data,
      type:options.type,
      dataType: options.dataType,
      success: function (res) {
        resolve(res)
      }
    })
  })

  // Return my promise object
  return p
}

myPromiseAjax({
    url: 'http://localhost:8888/test/first'
  })
  .then(res => {
    console.log('The first request is over')
    console.log(res)

    // return a new promise object
    return myPromiseAjax({
      url: 'http://localhost:8888/test/second',
      dataType: 'json'
    })
  })
  .then(res => {
    console.log('Second request result')
    console.log(res)

    // return a new promise object
    return myPromiseAjax({
      url: 'http://localhost:8888/test/third',
      data: 'name=Jack&age=20',
      dataType: 'json'
    })
  })
  .then(res => {
    console.log('Results of the third request')
    console.log(res)
  })

5. async function and await keyword

  • Syntax between ES7 and es8

  • effect:

  • In order to solve the Promise problem, write the Promise code more gracefully

  • Core function: write asynchronous code to look like synchronous code, but the essence is asynchronous

Syntax:

=>Async keyword (asynchronous)

  • Use: write in front of the function

(it can be a declarative function, a function expression, or an arrow function)

// async syntax
async function fn() {}
const fn = async function () {}
const fn = async a => {}

effect:

  1. The await keyword can be used in this function

  2. It will turn this function into an asynchronous function, just called an asynchronous function

    (this asynchronous function is not our real asynchronous code, but gives this function a name)

    =>It affects the code inside the function and does not affect the code outside the function

await keyword (wait)

  • requirement:
  1. await must be written inside an asynchronous function with async keyword

  2. What await waits for must be a promise object, otherwise it can't wait

  • effect:

    =>The results in promise that should have been accepted by the code in then,

    Variable acceptance can be defined directly in front of await

    =>Subsequent code will not be executed until promise is executed

console.log('start')	// ① start
async function fn() {
  console.log('I am fn Code inside the function')	// ②
  // Because pAjax is code encapsulated according to the syntax form of promise
  // pAjax returns a promise object
  // fn function, when the code of pAjax is executed
  // Will wait until the asynchronous code is completely executed and the result is assigned to r1
  // Continue to execute the following code
  const r1 = await pAjax({ url: 'http://localhost:8888/test/first' })
  console.log(r1)	// ④
}
fn()
console.log('end')	// ③ end

console.log('start')

async function fn() {
  console.log('I am fn Code inside the function')
  // At this point, the await keyword can be used in the fn function

  // The promise object returned by pAjax will execute
  // Assign the contents in parentheses to r1 during resolve(). Continue to execute the code backward
  const r1 = await myPromiseAjax({ url: 'http://localhost:8888/test/first' })
  console.log(r1)

  // //Demand 2:
  const r2 = await myPromiseAjax({
    url: 'http://localhost:8888/test/second',
    dataType: 'json'
  })
  console.log(r2)

  // Demand 3:
  const r3 = await myPromiseAjax({
    url: 'http://localhost:8888/test/third',
    data: 'name=Jack&age=20',
    dataType: 'json'
  })
  console.log(r3)
}

fn()

console.log('end')

Keywords: Javascript

Added by MVSS on Tue, 28 Sep 2021 20:44:03 +0300