Asynchrony and callback

What is a callback

A function that is written but not called, and is called by others, is the callback **

A callback is a function that you write but don’t call yourself, but give to someone else to call. When I write a function and say, “Dude, why don’t you call this function sometime in the future?”

Callbacks can be passed to functions as arguments to get called, or to an object for the browser to call.

A callback can also be an object that contains the actual callback function.

For example,

  1. AJAX asynchronous tasks in the request. The onreadystatechange is a callback function, the XMLHttpRequest object to 1, then to the browser calls.

  2. I wrote f1, f2 called f1 as his argument, so F1 is the callback. F1 is the callback passed to a function as an argument to be called

function f1(){}
function f2(fn){
    fn()
}
f2(f1)
Copy the code
  1. I write f1, f2 calls F1 when his argument, the effect is to give ‘hello’ to F1 when the argument executes F1. F1 is the callback passed to a function as an argument to be called
Function f1(x){console.log(x)} function f2(fn){fn(' hello ')} f2(f1)Copy the code

What is asynchrony

If you can get the result directly, it’s synchronization

If you can’t get the results straight, then yesasynchronous

Determine asynchronous or synchronous

A function is asynchronous if its result is inside one of these things

  • setTimeout
  • AJAX(i.e.XMLHttpRequest(Note: AJAX can only be asynchronous, so if you set the request to synchronous, the page will be stuck)
  • AddEventListener

For example – AJAX

const request = new XMLHttpRequest(); request.open("get", "/style.css"); //readyState=1 request.onreadystatechange = () => { console.log(request.readyState); If (request.readyState === 4) {console.log(" download complete "); // If (request.readyState === 4) {console.log(" download complete "); if (request.status >= 200 && request.status < 300) { const style = document.createElement("style"); style.innerHTML = request.response; document.head.appendChild(style); } else {alert(" failed to load CSS "); }}}; request.send();Copy the code
  • The Ajax asynchronous task wants response, but we can’t get it

  • In step 4 request.send(); Request. Send () readyState === 2

  • So as we learned before, we have to wait until readyState === 4 before we get response.

How do we get the results? Using callback = in the third step, we wrote a callback function request. The onreadystatechange passed an object. We want the result response to be an argument in the callback function.

  • When the Ajax asynchronous task completes, the resultresponseYes, but this result requires the browser to go back to the third step and use the callback function to get the resultresponse(Or the resultsresponseDo the deformation of the body form of the callback function.
  • In fact, every timereadyStateChange, and the browser will call back the callback functionrequest.onreadystatechangeOnce, it was justreadyStateThis callback function will only be true when it becomes 4response(Do what

For example — roll a die

Function (){setTimeout(()=>{return parseInt(math.random () * 6) + 1},1000) // undefined}Copy the code
  • Roll the dice ()Didn’t writereturn, that is,return undefined
  • The arrow function has itreturnReturns the real result
  • soRoll the dice ()Is an asynchronous function/task

How does this asynchronous task get results? Here we get the result through a callback

  1. Let’s start with a callback function

function f1(x) { console.log(x) }

  1. Let the asynchronous task call the callback function when the asynchronous task completes

Roll the dice (f1)

  1. The asynchronous task must be defined as a function, otherwise how can the callback function be an asynchronous task parameter?
  2. It is also necessary to take the result as an argument to the callback function, and then execute the callback function in the asynchronous task
  3. When the asynchronous task that takes the callback is executed in the second step, the result can be manipulated as the body of the callback
Function (fn){setTimeout(()=>{fn(return parseInt(math.random () * 6) + 1)},1000) // undefined}Copy the code

Third, summary

1. The asynchronous

  • Asynchronous tasks cannot get results
  • So we have to write a callback, and it turns out that the argument to the callback function, the callback function, will distort and render the result
  • We then pass this callback to the asynchronous function as a parameter or to an object as a property of the asynchronous task
  • Finally the callback function is called when the asynchronous function finishes and the browser calls the callback function that hangs on the object when the argument or asynchronous task completes
  • Note that when writing asynchronous functions/tasks, the callback function must be called with the result as an argument to the callback-function so that the callback function will distort and render the result
  • When the asynchronous function/task completes, the asynchronous function/task calls the callback function and executes the callback function, which calls the result and operates on the result

2. Asynchrony and callback — just a cooperative relationship, not bound to each other

  • Asynchronous tasks require callback functions to notify the result
  • But callbacks are not necessarily limited to asynchronous tasks
  • Callbacks can be used in synchronization tasks
  • array.forEach( n => console.log(n) )It’s a synchronous callback

Promise — JS asynchronous programming model, a unified solution to asynchronous problems in front end at present

Be sure to see the Promise MDN document

Promises/A + specification

1. The origin of promise

In 1976, Daniel P. Friedman and David Wise came up with the idea of Promise

  • Later generations invented Future, Delay, Deferred and so on based on this
  • The front end cribs Promise and JS to make Promises/A+ specifications that detail how Promise works and how to use it

2. Why promise?

  1. Promise to use
  2. The following approaches to asynchronous problems have many drawbacks
  • Non-standard, successful callback and failed callback names are various, such as SUCCESS +error, SUCCESS +fail, done+fail
  • Prone to callback hell, the code looks scary
  • Error handling is difficult
// If the result has two successes and two failures, how to solve the asynchronous problem how to get two results // method one (all node.js asynchronous apis have this method!) This callback takes two arguments: the result of failure and the result of success. If the first argument is error, the result of failure is present. If the first argument does not exist, that is, there is no failure, then the second argument is the result of success, data, which we turn into a string and return. // The readFile asynchronous function takes the first argument to the file path and the second argument to the callback function. Fs.readfile ('./1.txt', (error, data)=>{if(error){console.log(' failed '); Return} console.log(data.tostring ()) //}) // Return console.log(data.tostring ()) // Json ('get','/1.json', data=>{}, error=>{}) // Method 3: Use a callback object that contains two real callback functions. Json ('get', '/1.json', {success: ()=>{}, fail: ()=>{}})Copy the code

3. Elementary use of Promise (encapsulating Ajax as an example)

  1. First, in my last blog post, I learned the four steps of Ajax. It’s too much work, so wrap it up in a simple API
Ajax = (method, URL, options)=>{// Ajax is an asynchronous function, the last argument calls the callback function object, Const {success, fail} = options const {success, fail} = options Call it success and fail const request = new XMLHttpRequest() request.open(method, Url) request. The onreadystatechange = () = > {/ / the first return to adjust the if (request. ReadyState = = = 4) {/ / after the asynchronous task is complete, we can't get the result, If (request.status < 400){if(request.status < 400){if(request.status < 400){if(request.status < 400){if(request.status < 400){if(request.status < 400){if(request.status < 400){if(request.status < 400){if(request.status < 400){ }else if(request.status >= 400){// Fail. Call (null, request, request.status) // Call the fail callback. And pass the resulting request and status parameters to the callback function. }} request. Send ()} // Perform ajax asynchronous functions ajax('get', '/ XXX ', {success(response){}, fail: (Request, status)=>{}}) // Write both the success and failure callback functions in the callback objectCopy the code
  1. Modify the package above with promise
Ajax = (method, url) => {return new Promise((resolve, reject) => {// This object has an API called then //②Promise. The constructor argument is a function (resolve and reject). Const request = new XMLHttpRequest() request.open(method, XMLHttpRequest()) Url) request. The onreadystatechange = () = > {the if (request. ReadyState = = = 4) {/ / asynchronous function complete callback (level) will call this function if (request. The status" 400) {resolve. Call (null, request.response) // Call the resolve callback if the result is successful. Reject (request. Status >= 400) {reject. Call (null, request)} else if (request. }} request. Send ()})} // Perform ajax asynchronous functions ajax('get', '/ XXX ') then((response)=>{}, (request, Resolve (reject); reject (reject); reject (reject); reject (reject)Copy the code

(1) Specific steps to transform the encapsulated Ajax asynchronous function with Promise

  • Return a Promise objectreturn new Promise((resolve, reject) => { })
  • Everything else is in{}In the
  • Asynchronous task success is calledresolveA callback function (taking the result as an argument) whose failure is the callrejectCallback function (taking result as argument)

(2) Execute the wrapped Ajax asynchronous function transformed with Promise

When an asynchronous function is executed, it is followed by a. Then (success callback (result), failure callback (result)), thus passing in the success and failure callbacks. (3) Some fragmentary attention points

  • window.PromiseIs a global function that can be constructedPromiseobject
  • usereturn new Promise((resolve, reject)=> {}) You can construct onePromiseobject
  • The constructed Promise object contains one.then() Function attributes
  • resolverejectYou can change it to any other name and it doesn’t affect use, but these two names are generally used
  • Called when the task succeedsresolve, is called on failurereject
  • resolverejectEach accepts only one parameter
  • resolverejectIs not.then(succes, fail)The inside of thesuccessfail.resolveGoing to callsuccess.rejectGoing to callfail
  • ajax.get('/xxx')Return a Promise object
  • ajax.get('/xxx').then(s, f)Called when the request succeedss, failed use callf

Ajax libraries

JQuery wrapper – jquery.ajax

  • If you are interested, go to the official jQuery documentation and search for Ajax
  • Support for more forms of parameters
  • Supporting Promise
  • There are so many features supported
  • But you don’t need jquery.Ajax, the professional front end is using Axios

Axios – The latest Ajax library

  • Must see Axios Chinese documentation and AXIos Cheat Sheet
  • Supporting Promise
  • Copying jQuery encapsulation ideas
  • axios.get('/xxx')Return a Promise object
  • axios.get('/xxx').then(s, f)Called when the request succeedss, failed use callf

Advanced usage

  1. JSON automatic processing
  • How does Axios automatically call json.parse when it finds that the content-type of the response is JSON
  • So setting content-Type correctly is good practice
  1. Request interceptor
  • You can add something to all requests, such as query parameters
  1. Response interceptor
  • You can add something to all the responses, or even change the content
  1. Can generate different instances (objects)

Different instances can set different configurations for complex scenarios