javascript 异步_JavaScript异步编程和回调

javascript 异步

编程语言中的异步性 (Asynchronicity in Programming Languages)

Computers are asynchronous by design.

计算机在设计上是异步的。

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

异步意味着事情可以独立于主程序流发生。

In the current consumer computers, every program runs for a specific time slot, and then it stops its execution to let another program continue its execution. This thing runs in a cycle so fast that’s impossible to notice, and we think our computers run many programs simultaneously, but this is an illusion (except on multiprocessor machines).

在当前的消费计算机中,每个程序都运行特定的时间段,然后停止执行,让另一个程序继续执行。 这件事的运行周期如此之快,以至于无法察觉,我们认为我们的计算机可以同时运行许多程序,但这只是一种幻想(在多处理器计算机上除外)。

Programs internally use interrupts, a signal that’s emitted to the processor to gain the attention of the system.

程序在内部使用中断 ,该信号被发送到处理器以引起系统的注意。

I won’t go into the internals of this, but just keep in mind that it’s normal for programs to be asynchronous, and halt their execution until they need attention, and the computer can execute other things in the meantime. When a program is waiting for a response from the network, it cannot halt the processor until the request finishes.

我不会深入探讨这个问题,只是要记住,程序异步是正常的,并且在需要注意之前停止执行,计算机可以同时执行其他操作。 当程序正在等待来自网络的响应时,它无法在请求完成之前停止处理器。

Normally, programming languages are synchronous, and some provide a way to manage asynchronicity, in the language or through libraries. C, Java, C#, PHP, Go, Ruby, Swift, Python, they are all synchronous by default. Some of them handle async by using threads, spawning a new process.

通常,编程语言是同步的,并且某些编程语言提供了一种通过语言或通过库来管理异步性的方法。 C,Java,C#,PHP,Go,Ruby,Swift,Python,默认情况下它们都是同步的。 其中一些通过使用线程来处理异步操作,从而产生一个新进程。

JavaScript (JavaScript)

JavaScript is synchronous by default and is single threaded. This means that code cannot create new threads and run in parallel.

JavaScript默认情况下是同步的 ,并且是单线程的。 这意味着代码无法创建新线程并不能并行运行。

Lines of code are executed in series, one after another, for example:

几行代码依次执行,例如:

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

But JavaScript was born inside the browser, its main job, in the beginning, was to respond to user actions, like onClick, onMouseOver, onChange, onSubmit and so on. How could it do this with a synchronous programming model?

但是JavaScript诞生于浏览器内部,一开始它的主要工作是响应用户操作,例如onClickonMouseOveronChangeonSubmit等。 如何使用同步编程模型来做到这一点?

The answer was in its environment. The browser provides a way to do it by providing a set of APIs that can handle this kind of functionality.

答案在于它的环境。 浏览器通过提供一组可以处理这种功能的API提供了一种实现方法。

More recently, Node.js introduced a non-blocking I/O environment to extend this concept to file access, network calls and so on.

最近,Node.js引入了非阻塞I / O环境,以将该概念扩展到文件访问,网络调用等。

回呼 (Callbacks)

You can’t know when a user is going to click a button, so what you do is, you define an event handler for the click event. This event handler accepts a function, which will be called when the event is triggered:

您不知道用户何时单击按钮,因此,您需要为click event定义事件处理程序 。 该事件处理程序接受一个函数,该函数将在触发事件时被调用:

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

This is the so-called callback.

这就是所谓的callback

A callback is a simple function that’s passed as a value to another function, and will only be executed when the event happens. We can do this because JavaScript has first-class functions, which can be assigned to variables and passed around to other functions (called higher-order functions)

回调是一个简单的函数,将其作为值传递给另一个函数,并且仅在事件发生时才执行。 我们之所以这样做,是因为JavaScript具有一流的函数,这些函数可以分配给变量并传递给其他函数(称为高阶函数 )。

It’s common to wrap all your client code in a load event listener on the window object, which runs the callback function only when the page is ready:

通常将所有客户端代码包装在window对象的load事件监听器中,该对象仅在页面准备就绪时才运行回调函数:

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

Callbacks are used everywhere, not just in DOM events.

回调无处不在,不仅在DOM事件中使用。

One common example is by using timers:

一个常见的示例是使用计时器:

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

XHR requests also accept a callback, in this example by assigning a function to a property that will be called when a particular event occurs (in this case, the state of the request changes):

XHR请求还接受回调,在此示例中,将一个函数分配给一个属性,该属性将在发生特定事件时被调用(在这种情况下,请求的状态会发生变化):

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 errors with callbacks? One very common strategy is to use what Node.js adopted: the first parameter in any callback function is the error object: error-first callbacks

您如何处理回调错误? 一个非常常见的策略是使用Node.js所采用的方法:任何回调函数中的第一个参数是错误对象: error-first回调

If there is no error, the object is null. If there is an error, it contains some description of the error and other information.

如果没有错误,则该对象为null 。 如果有错误,它将包含对该错误的一些描述以及其他信息。

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

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

回调的问题 (The problem with callbacks)

Callbacks are great for simple cases!

回调适用于简单情况!

However every callback adds a level of nesting, and when you have lots of callbacks, the code starts to be complicated very quickly:

但是,每个回调都会添加一个嵌套级别,并且当您有很多回调时,代码会很快变得非常复杂:

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

This is just a simple 4-levels code, but I’ve seen much more levels of nesting and it’s not fun.

这只是一个简单的4级代码,但是我看到了更多的嵌套级别,这很不好玩。

How do we solve this?

我们该如何解决呢?

回调的替代方法 (Alternatives to callbacks)

Starting with ES6, JavaScript introduced several features that help us with asynchronous code that do not involve using callbacks:

从ES6开始,JavaScript引入了一些功能,这些功能可以帮助我们处理不涉及使用回调的异步代码:

翻译自: https://flaviocopes.com/javascript-callbacks/

javascript 异步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值