JavaScript asynchronous programming and callbacks

JavaScript is synchronous by default and is single-threaded. This means that the code cannot create new threads and cannot run in parallel. Find out what the asynchronous code means and what it looks like

Asynchrony in programming languages

Computers are asynchronous by design.

Asynchronous means that things can happen independently of the main program flow.

In current consumer computers, each program runs for a specific period of time, and then stops execution to allow another program to continue execution. The cycle of this event is so fast that it is impossible to notice that we think that our computer can run many programs at the same time, but this is an illusion (except on a multi-processor computer).

Internal use of the programinterrupt, The signal is sent to the processor to attract the attention of the system.

I won't go into this issue in depth, just remember that asynchronous programs are normal and stop execution before needing attention, and the computer can perform other operations at the same time. When the program is waiting for a response from the network, it cannot stop the processor before the request is completed.

Generally, programming languages are synchronous, and some programming languages provide a way to manage asynchrony through language or through libraries. C, Java, C#, PHP, Go, Ruby, Swift, Python, they are all synchronized by default. Some of them use threads to handle asynchronous operations, thereby spawning a new process.

JavaScript

JavaScript isSynchronizeSingle threaded by default. This means that the code cannot create new threads and cannot run in parallel.

The lines of code are executed one after the other, for example:

const a = 1
const b = 2
const c = a * b
console.log(c)
doSomething()

But JavaScript was born inside the browser. At the beginning, its main job was to respond to user operations, such asonClick,onMouseOver,onChange,onSubmitand many more. How to use the synchronous programming model to do this?

The answer lies in its environment. ThisBrowserProvide an implementation method by providing a set of APIs that can handle this function.

Recently, Node.js introduced a non-blocking I/O environment to extend the concept to file access, network calls, etc.

Call back

You don’t know when the user clicks the button, so what you have to do is,Define an event handler for the click event. This event handler accepts a function that will be called when the event is triggered:

document.getElementById('button').addEventListener('click', () => {
  //item clicked
})

This is calledcall back.

A callback is a simple function that is passed as a value to another function and is only executed when an event occurs. We do this because JavaScript has first-class functions that can be assigned to variables and passed to other functions (calledHigher order function)

Usually wrap all client code in oneloadEvent listenerwindowObject, the callback function is run only when the page is ready:

window.addEventListener('load', () => {
  //window loaded
  //do what you want
})

Callbacks are everywhere, not only in DOM events.

A common example is the use of timers:

setTimeout(() => {
  // runs after 2 seconds
}, 2000)

XHR requests also accept callbacks. In this example, a function is assigned to a property that will be called when a specific event occurs (in this case, the state of the request changes):

const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
  if (xhr.readyState === 4) {
    xhr.status === 200 ? console.log(xhr.responseText) : console.error('error')
  }
}
xhr.open('GET', 'https://yoursite.com')
xhr.send()

Handling errors in callbacks

How do you handle callback errors? A very common strategy is to use the method adopted by Node.js: the first parameter in any callback function is the error object:Error priority callback

If there are no errors, the object isnull. If there is an error, it will contain some description of the error and other information.

fs.readFile('/file.json', (err, data) => {
  if (err !== null) {
    //handle error
    console.log(err)
    return
  }

//no errors, process data console.log(data) })

Callback problem

Callbacks are suitable for simple situations!

However, each callback adds a nesting level, and when you have many callbacks, the code can quickly become very complicated:

window.addEventListener('load', () => {
  document.getElementById('button').addEventListener('click', () => {
    setTimeout(() => {
      items.forEach(item => {
        //your code here
      })
    }, 2000)
  })
})

This is just a simple 4-level code, but I see more nesting levels, which is not fun.

How can we solve it?

Alternatives to callbacks

Starting from ES6, JavaScript has introduced some features that can help us deal with asynchronous code that does not involve the use of callbacks:

Download mine for freeJavaScript beginner's manual


More js tutorials: