1. 程式人生 > 實用技巧 >nodejs.cn-Node.js-入門教程:JavaScript 非同步程式設計與回撥

nodejs.cn-Node.js-入門教程:JavaScript 非同步程式設計與回撥

ylbtech-nodejs.cn-Node.js-入門教程:JavaScript 非同步程式設計與回撥

1.返回頂部
1、

JavaScript 非同步程式設計與回撥

目錄

程式語言中的非同步性

計算機在設計上是非同步的

非同步意味著事情可以獨立於主程式流而發生

在當前的使用者計算機中,每個程式都運行於特定的時間段,然後停止執行,以讓另一個程式繼續執行。 這件事執行得如此之快,以至於無法察覺。 我們以為計算機可以同時執行許多程式,但這是一種錯覺(在多處理器計算機上除外

)。

程式在內部會使用中斷,一種被髮送到處理器以獲取系統關注的訊號。

這裡不會深入探討這個問題,只要記住,程式是非同步的且會暫停執行直到需要關注,這使得計算機可以同時執行其他操作。 當程式正在等待來自網路的響應時,則它無法在請求完成之前停止處理器。

通常,程式語言是同步的,有些會在語言或庫中提供管理非同步性的方法。 預設情況下,C、Java、C#、PHP、Go、Ruby、Swift 和 Python 都是同步的。 其中一些語言通過使用執行緒(衍生新的程序)來處理非同步操作。

JavaScript

JavaScript 預設情況下是同步的,並且是單執行緒的。 這意味著程式碼無法建立新的執行緒並且不能並行執行

程式碼行是依次執行的,例如:

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

但是 JavaScript 誕生於瀏覽器內部,一開始的主要工作是響應使用者的操作,例如onClickonMouseOveronChangeonSubmit等。 使用同步的程式設計模型該如何做到這一點?

答案就在於它的環境。 瀏覽器通過提供一組可以處理這種功能的 API 來提供了一種實現方式。

更近點,Node.js 引入了非阻塞的 I/O 環境,以將該概念擴充套件到檔案訪問、網路呼叫等。

回撥

你不知道使用者何時單擊按鈕。 因此,為點選事件定義了一個事件處理程式。 該事件處理程式會接受一個函式,該函式會在該事件被觸發時被呼叫:

document.getElementById('button').addEventListener('click', () => {
  //被點選
})

這就是所謂的回撥。

回撥是一個簡單的函式,會作為值被傳給另一個函式,並且僅在事件發生時才被執行。 之所以這樣做,是因為 JavaScript 具有頂級的函式這些函式可以被分配給變數並傳給其他函式(稱為高階函式)。

通常會將所有的客戶端程式碼封裝在window物件的load事件監聽器中,其僅在頁面準備就緒時才會執行回撥函式:

window.addEventListener('load', () => {
  //window 已被載入。
  //做需要做的。
})

回撥無處不在,不僅在 DOM 事件中

一個常見的示例是使用定時器:

setTimeout(() => {
  // 2 秒之後執行。
}, 2000)

XHR 請求也接受回撥,在此示例中,會將一個函式分配給一個屬性,該屬性會在發生特定事件(在該示例中,是請求狀態的改變)時被呼叫:

const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
  if (xhr.readyState === 4) {
    xhr.status === 200 ? console.log(xhr.responseText) : console.error('出錯')
  }
}
xhr.open('GET', 'http://nodejs.cn')
xhr.send()

處理回撥中的錯誤

如何處理回撥的錯誤? 一種非常常見的策略是使用 Node.js 所採用的方式:任何回撥函式中的第一個引數為錯誤物件(即錯誤優先的回撥)

如果沒有錯誤,則該物件為null。 如果有錯誤,則它會包含對該錯誤的描述以及其他資訊。

fs.readFile('/檔案.json', (err, data) => {
  if (err !== null) {
    //處理錯誤
    console.log(err)
    return
  }

  //沒有錯誤,則處理資料。
  console.log(data)
})

回撥的問題

回調適用於簡單的場景!

但是,每個回撥都可以新增巢狀的層級,並且當有很多回調時,程式碼就會很快變得非常複雜:

window.addEventListener('load', () => {
  document.getElementById('button').addEventListener('click', () => {
    setTimeout(() => {
      items.forEach(item => {
        //你的程式碼在這裡。
      })
    }, 2000)
  })
})

這只是一個簡單的 4 個層級的程式碼,但還有更多層級的巢狀,這很不好。

該如何解決?

回撥的替代方法

從 ES6 開始,JavaScript 引入了一些特性,可以幫助處理非同步程式碼而不涉及使用回撥:Promise(ES6)和 Async/Await(ES2017)

2、
2.返回頂部
3.返回頂部
4.返回頂部
5.返回頂部
1、 http://nodejs.cn/learn/javascript-asynchronous-programming-and-callbacks 2、
6.返回頂部
作者:ylbtech
出處:http://ylbtech.cnblogs.com/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。