目錄
1、回呼函數
2、同步回呼
总结
首頁 web前端 js教程 深入解析JavaScript中的回呼函數(同步與非同步)

深入解析JavaScript中的回呼函數(同步與非同步)

Aug 04, 2022 am 10:05 AM
javascript 前端 回呼函數

回呼函數是每個前端程式設計師都應該知道的概念之一。回調可用於陣列、計時器函數、promise、事件處理。本文將會解釋回呼函數的概念,同時幫你區分兩種回呼:同步和非同步。

深入解析JavaScript中的回呼函數(同步與非同步)

1、回呼函數

#先寫一個向人打招呼的函數。

只需要建立一個接受 name 參數的函數 greet(name)。這個函數要回傳打招呼的訊息:

function greet(name) {
  return `Hello, ${name}!`;
}

greet('Cristina'); // => 'Hello, Cristina!'
登入後複製

如果向很多人打招呼該怎麼辦?可以用特殊的陣列方法 array.map() 可以實作:

const persons = ['Cristina', 'Ana'];

const messages = persons.map(greet);
messages; // => ['Hello, Cristina!', 'Hello, Ana!']
登入後複製

persons.map(greet) 可以取得persons 陣列的所有元素,並分別以每個元素作為呼叫參數來呼叫greet() 函數:`greet('Cristina'), greet('Ana')

有趣的是 persons.map(greet) 方法可以接受 greet()  函數作為參數。這樣 greet()  就變成了回呼函數

persons.map(greet) 是用另一個函數作為參數的函數,因此稱為高階函數

回呼函數作為高階函數的參數,高階函數透過呼叫回呼函數來執行操作。

重要的是高階函數負責呼叫回調,並為其提供正確的參數。

前面的範例中,高階函數persons.map(greet) 負責呼叫 greet()  函數,並且分別將陣列中所有的元素'Cristina'Ana ' 作為參數。

這就為識別回呼提供了一條簡單的規則。如果你定義了一個函數,並將其作參數提供給另一個函數的話,那麼這就創建了一個回呼。

你可以自己寫一個使用回呼的高階函數。以下是array.map() 方法的等效版本:

function map(array, callback) {
  const mappedArray = [];
  for (const item of array) { 
    mappedArray.push(
      callback(item)    );
  }
  return mappedArray;
}

function greet(name) {
  return `Hello, ${name}!`;
}

const persons = ['Cristina', 'Ana'];

const messages = map(persons, greet);messages; // => ['Hello, Cristina!', 'Hello, Ana!']
登入後複製

map(array, callback) 是高階函數,因為它用回呼函數作為參數,然後在其主體內部呼叫該回呼函數:callback(item)

注意,常規函數(以關鍵字 function 定義)或箭頭函數(以粗箭頭 => 定義)同樣可以作為回調使用。

2、同步回呼

回呼的呼叫方式有兩種:同步非同步回呼。

同步回呼是「阻塞」的:高階函數直到回呼函數完成後才繼續執行。

例如,呼叫 map()greet() 函數。

function map(array, callback) {
  console.log('map() starts');
  const mappedArray = [];
  for (const item of array) { mappedArray.push(callback(item)) }
  console.log('map() completed');
  return mappedArray;
}

function greet(name) {
  console.log('greet() called');
  return `Hello, ${name}!`;
}

const persons = ['Cristina'];

map(persons, greet);
// logs 'map() starts'
// logs 'greet() called'
// logs 'map() completed'
登入後複製

其中 greet()  是同步回呼。

同步回呼的步驟:

  • 高階函數開始執行:'map() starts'

  • ##回呼函數執行:

    'greet() called'

  • #.最後高階函數完成它自己的執行過程:

    'map() completed'

同步回呼的範例

許多原生JavaScript 類型的方法都會使用同步回呼。

最常用的是array 的方法,例如:

array.map(callback), array.forEach(callback), array.find(callback ), array.filter(callback), array.reduce(callback, init)

// Examples of synchronous callbacks on arrays
const persons = ['Ana', 'Elena'];

persons.forEach(
  function callback(name) {    console.log(name);
  }
);
// logs 'Ana'
// logs 'Elena'

const nameStartingA = persons.find(
  function callback(name) {    return name[0].toLowerCase() === 'a';
  }
);
nameStartingA; // => 'Ana'

const countStartingA = persons.reduce(
  function callback(count, name) {    const startsA = name[0].toLowerCase() === 'a';
    return startsA ? count + 1 : count;
  }, 
  0
);
countStartingA; // => 1
登入後複製
字串類型的

string.replace( callback)  方法也能接受同步執行的回呼:

// Examples of synchronous callbacks on strings
const person = 'Cristina';

// Replace 'i' with '1'
person.replace(/./g, 
  function(char) {    return char.toLowerCase() === 'i' ? '1' : char;
  }
); // => 'Cr1st1na'
登入後複製

#3、非同步回呼

非同步回呼是「非阻塞的」:高階函數無需等待回調完成即可完成其執行。高階函數可確保稍後在特定事件上執行回呼。

在以下的例子中,

later() 函數的執行延遲了2 秒:

console.log('setTimeout() starts');
setTimeout(function later() {
  console.log('later() called');
}, 2000);
console.log('setTimeout() completed');

// logs 'setTimeout() starts'
// logs 'setTimeout() completed'
// logs 'later() called' (after 2 seconds)
登入後複製

later() 是一個非同步回調,因為setTimeout(later,2000) 啟動並完成了執行,但是later() 在2 秒後執行。

非同步呼叫回呼的步驟:

  • 高階函數開始執行:

    'setTimeout()starts'

  • 高階函數完成其執行:

    'setTimeout() completed'

  • # 回呼函數在2 秒後執行:

    'later( ) called'

異步回呼的範例

計時器函數非同步呼叫回呼:

setTimeout(function later() {
  console.log('2 seconds have passed!');
}, 2000);
// After 2 seconds logs '2 seconds have passed!' 

setInterval(function repeat() {
  console.log('Every 2 seconds');
}, 2000);
// Each 2 seconds logs 'Every 2 seconds!'
登入後複製
#DOM 事件偵聽器也非同步呼叫事件處理函數(回呼函數的子類型):

const myButton = document.getElementById('myButton');

myButton.addEventListener('click', function handler() {
  console.log('Button clicked!');
});
// Logs 'Button clicked!' when the button is clicked
登入後複製

#4、非同步回呼函數與非同步函數

在函數定義之前加上特殊關鍵字

async 會建立一個非同步函數:

async function fetchUserNames() {
  const resp = await fetch('https://api.github.com/users?per_page=5');
  const users = await resp.json();
  const names = users.map(({ login }) => login);
  console.log(names);
}
登入後複製

fetchUserNames() 是异步的,因为它以 async 为前缀。函数  await fetch('https://api.github.com/users?per_page=5') 从 GitHub 上获取前5个用户 。然后从响应对象中提取 JSON 数据:await resp.json()

异步函数是 promise 之上的语法糖。当遇到表达式 await <promise>  (调用  fetch()  会返回一个promise)时,异步函数会暂停执行,直到 promise 被解决。

异步回调函数和异步函数是不同的两个术语。

异步回调函数由高阶函数以非阻塞方式执行。但是异步函数在等待 promise(await <promise>)解析时会暂停执行。

但是你可以把异步函数用作异步回调!

让我们把异步函数 fetch UserNames() 设为异步回调,只需单击按钮即可调用:

const button = document.getElementById('fetchUsersButton');

button.addEventListener('click', fetchUserNames);
登入後複製

总结

回调是一个可以作为参数传给另一个函数(高阶函数)执行的函数。

回调函数有两种:同步和异步。

  • 同步回调是阻塞的。

  • 异步回调是非阻塞的。

【相关推荐:javascript学习教程

以上是深入解析JavaScript中的回呼函數(同步與非同步)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

java回呼函數怎麼寫 java回呼函數怎麼寫 Jan 09, 2024 pm 02:24 PM

java回調函數的寫法有:1、接口回調,定義一個接口,其中包含一個回調方法,在需要觸發回調的地方,使用該接口作為參數,並在合適的時機調用回調方法;2、匿名內部類回調,可以使用匿名內部類別來實現回調函數,避免創建額外的實作類別;3、Lambda表達式回調,在Java 8以上版本中,可以使用Lambda表達式來簡化回調函數的寫法等。

PHP與Vue:完美搭檔的前端開發利器 PHP與Vue:完美搭檔的前端開發利器 Mar 16, 2024 pm 12:09 PM

PHP與Vue:完美搭檔的前端開發利器在當今網路快速發展的時代,前端開發變得愈發重要。隨著使用者對網站和應用的體驗要求越來越高,前端開發人員需要使用更有效率和靈活的工具來創建響應式和互動式的介面。 PHP和Vue.js作為前端開發領域的兩個重要技術,搭配起來可以稱得上是完美的利器。本文將探討PHP和Vue的結合,以及詳細的程式碼範例,幫助讀者更好地理解和應用這兩

前端面試官常問的問題 前端面試官常問的問題 Mar 19, 2024 pm 02:24 PM

在前端開發面試中,常見問題涵蓋廣泛,包括HTML/CSS基礎、JavaScript基礎、框架和函式庫、專案經驗、演算法和資料結構、效能最佳化、跨域請求、前端工程化、設計模式以及新技術和趨勢。面試官的問題旨在評估候選人的技術技能、專案經驗以及對行業趨勢的理解。因此,應試者應充分準備這些方面,以展現自己的能力和專業知識。

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

Django是前端還是後端?一探究竟! Django是前端還是後端?一探究竟! Jan 19, 2024 am 08:37 AM

Django是一個由Python編寫的web應用框架,它強調快速開發和乾淨方法。儘管Django是web框架,但要回答Django是前端還是後端這個問題,需要深入理解前後端的概念。前端是指使用者直接和互動的介面,後端是指伺服器端的程序,他們透過HTTP協定進行資料的互動。在前端和後端分離的情況下,前後端程式可以獨立開發,分別實現業務邏輯和互動效果,資料的交

Go語言前端技術探秘:前端開發新視野 Go語言前端技術探秘:前端開發新視野 Mar 28, 2024 pm 01:06 PM

Go語言作為一種快速、高效的程式語言,在後端開發領域廣受歡迎。然而,很少有人將Go語言與前端開發聯繫起來。事實上,使用Go語言進行前端開發不僅可以提高效率,還能為開發者帶來全新的視野。本文將探討使用Go語言進行前端開發的可能性,並提供具體的程式碼範例,幫助讀者更了解這一領域。在傳統的前端開發中,通常會使用JavaScript、HTML和CSS來建立使用者介面

Java中回呼函數的基本語法與應用 Java中回呼函數的基本語法與應用 Jan 30, 2024 am 08:12 AM

Java回呼函數的基本寫法和使用方法引言:在Java程式設計中,回呼函數是一種常見的程式模式,透過回呼函數,可以將某個方法作為參數傳遞給另一個方法,從而實現方法的間接呼叫。回調函數的使用,在事件驅動、非同步程式設計和介面實作等場景中非常常見。本文將介紹Java回呼函數的基本寫法和使用方法,並提供具體的程式碼範例。一、回呼函數的定義回呼函數是一種特殊的函數,它可以作為參數

Django:前端和後端開發都能搞定的神奇框架! Django:前端和後端開發都能搞定的神奇框架! Jan 19, 2024 am 08:52 AM

Django:前端和後端開發都能搞定的神奇框架! Django是一個高效、可擴展的網路應用程式框架。它能夠支援多種Web開發模式,包括MVC和MTV,可以輕鬆地開發出高品質的Web應用程式。 Django不僅支援後端開發,還能夠快速建構出前端的介面,透過模板語言,實現靈活的視圖展示。 Django把前端開發和後端開發融合成了一種無縫的整合,讓開發人員不必專門學習

See all articles