您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)JavaScript回調(diào)函數(shù)的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
函數(shù)是在其中有一組代碼的邏輯構(gòu)件,用來執(zhí)行特定任務(wù)。實(shí)際上為了易于調(diào)試和維護(hù),函數(shù)允許以更有組織的方式去編寫代碼。函數(shù)還允許代碼重用。
你只需定義一次函數(shù),然后在需要時去調(diào)用它,而不必一次又一次地編寫相同的代碼。
現(xiàn)在,讓我們看看如何在 javascript 中聲明一個函數(shù)。
使用函數(shù)的構(gòu)造函數(shù): 在這種方法中,函數(shù)是在“函數(shù)”的構(gòu)造函數(shù)的幫助下創(chuàng)建的。從技術(shù)上講,這種方法比使用函數(shù)表達(dá)式語法和函數(shù)聲明語句語法去聲明函數(shù)的方法效率要低。
使用函數(shù)表達(dá)式: 通常這種方法與變量分配相同。簡而言之,函數(shù)主體被視為一個表達(dá)式,并且該表達(dá)式被分配給一個變量。使用這種語法定義的函數(shù)可以是命名函數(shù)或匿名函數(shù)。
沒有名稱的函數(shù)被稱為匿名函數(shù)。匿名函數(shù)是自調(diào)用的,這意味著它會自動調(diào)用起自身。這種行為也稱為立即調(diào)用的函數(shù)表達(dá)式(IIFE)。
使用函數(shù)聲明: 這種方法是 JavaScript 中常用的老派方法。在關(guān)鍵字“function”之后,你必須指定函數(shù)的名稱。之后,如果函數(shù)接受多個參數(shù)或參數(shù),也需要提及它們。雖然這部分是完全可選的。
在函數(shù)體中,函數(shù)必須將一個值返回給調(diào)用方。遇到 return 語句后,該函數(shù)將會停止執(zhí)行。在函數(shù)內(nèi)部,參數(shù)將會充當(dāng)局部變量。
同樣,在函數(shù)內(nèi)部聲明的變量是該函數(shù)的局部變量。局部變量只能在該函數(shù)內(nèi)訪問,因此具有相同名稱的變量可以輕松地用于不同的函數(shù)。
在下列任何一種情況下,將調(diào)用之前聲明的函數(shù):
發(fā)生事件時,例如,用戶單擊按鈕,或者用戶從下拉列表中選擇某些選項(xiàng)等等。
從 javascript 代碼中調(diào)用該函數(shù)時。
該函數(shù)可以自動調(diào)用,我們已經(jīng)在匿名函數(shù)表達(dá)式中進(jìn)行了討論。
() 運(yùn)算符調(diào)用該函數(shù)。
按照 MDN 的描述:回調(diào)函數(shù)是作為參數(shù)傳給另一個函數(shù)的函數(shù),然后通過在外部函數(shù)內(nèi)部調(diào)用該回調(diào)函數(shù)以完成某種操作。
讓我用人話解釋一下,回調(diào)函數(shù)是一個函數(shù),將會在另一個函數(shù)完成執(zhí)行后立即執(zhí)行?;卣{(diào)函數(shù)是一個作為參數(shù)傳給另一個 JavaScript 函數(shù)的函數(shù)。這個回調(diào)函數(shù)會在傳給的函數(shù)內(nèi)部執(zhí)行。
在 JavaScript 中函數(shù)被看作是一類對象。對于一類對象,我們的意思是指數(shù)字、函數(shù)或變量可以與語言中的其他實(shí)體相同。作為一類對象,可以將函數(shù)作為變量傳給其他函數(shù),也可以從其他函數(shù)中返回這些函數(shù)。
可以執(zhí)行這種操作的函數(shù)被稱為高階函數(shù)?;卣{(diào)函數(shù)實(shí)際上是一種模式?!澳J健币辉~表示解決軟件開發(fā)中常見問題的某種行之有效的方法。最好將回調(diào)函數(shù)作為回調(diào)模式去使用。
客戶端 JavaScript 在瀏覽器中運(yùn)行,并且瀏覽器的主進(jìn)程是單線程事件循環(huán)。如果我們嘗試在單線程事件循環(huán)中執(zhí)行長時間運(yùn)行的操作,則會阻止該過程。從技術(shù)上講這是不好的,因?yàn)檫^程在等待操作完成時會停止處理其他事件。
例如,alert 語句被視為瀏覽器中 javascript 中的阻止代碼之一。如果運(yùn)行 alert,則在關(guān)閉 alert 對話框窗口之前,你將無法在瀏覽器中進(jìn)行任何交互。為了防止阻塞長時間運(yùn)行的操作,我們使用了回調(diào)。
讓我們深入研究一下,以便使你準(zhǔn)確了解在哪種情況下使用回調(diào)。
獲取并顯示消息的函數(shù)
在上面的代碼片段中,首先執(zhí)行 getMessage()函數(shù),然后執(zhí)行 displayMessage() 。兩者都在瀏覽器的控制臺窗口中顯示了一條消息,并且都立即執(zhí)行。
在某些情況下,一些代碼不會立即執(zhí)行。例如,如果我們假設(shè) getMessage() 函數(shù)執(zhí)行 API 調(diào)用,則必須將請求發(fā)送到服務(wù)器并等待響應(yīng)。這時我們應(yīng)該如何處理呢?
我認(rèn)為與其告訴你 JavaScript 回調(diào)函數(shù)的語法,不如在前面的例子中實(shí)現(xiàn)回調(diào)函數(shù)更好。修改后的代碼段顯示在下面的截圖中。
用回調(diào)函數(shù)顯示消息
為了使用回調(diào)函數(shù),我們需要執(zhí)行某種無法立即顯示結(jié)果的任務(wù)。為了模擬這種行為,我們用 JavaScript 的 setTimeout() 函數(shù)。該函數(shù)會暫停兩秒鐘,然后在控制臺窗口中顯示消息“ Hi,there”。
“顯示的消息”將被顯示在瀏覽器的控制臺窗口中。在這種情況下,首先,我們需要等待 getMessage() 函數(shù)。成功執(zhí)行此函數(shù)后,再執(zhí)行 displayMessage() 函數(shù)。
讓我解釋一下前面的例子在幕后發(fā)生的事。
從上一個例子可以看到,在 getMessage() 函數(shù)中,我們傳遞了兩個參數(shù)。第一個參數(shù)是 msg 變量,該變量顯示在瀏覽器的控制臺窗口中,第二個參數(shù)是回調(diào)函數(shù)。
現(xiàn)在,你可能想知道為什么將回調(diào)函數(shù)作為參數(shù)進(jìn)行傳遞 —— 要實(shí)現(xiàn)回調(diào)函數(shù),我們必須將一個函數(shù)作為參數(shù)傳給另一個函數(shù)。
在 getMessage() 完成任務(wù)后,我們將調(diào)用回調(diào)函數(shù)。之后,當(dāng)調(diào)用 getMessage() 函數(shù)時,將引用傳給displayMessage() 函數(shù),該函數(shù)就是回調(diào)函數(shù)。
注意,當(dāng)調(diào)用 getMessage() 函數(shù)時,我們僅將其引用傳給 displayMessage() 函數(shù)。這就是為什么你不會在它旁邊看到函數(shù)調(diào)用運(yùn)算符,也就是() 符號。
JavaScript 被認(rèn)為是單線程腳本語言。單線程是指 JavaScript 一次執(zhí)行一個代碼塊。當(dāng) JavaScript 忙于執(zhí)行一個塊時,它不可能移到下一個塊。
換句話說,我們可以認(rèn)為 JavaScript 代碼本質(zhì)上總是阻塞的。但是這種阻塞性使我們無法在某些情況下編寫代碼,因?yàn)樵谶@些情況下我們沒有辦法在執(zhí)行某些特定任務(wù)后立即得到結(jié)果。
我談?wù)摰娜蝿?wù)包括以下情況:
通過對某些端點(diǎn)進(jìn)行 API 調(diào)用來獲取數(shù)據(jù)。
通過發(fā)送網(wǎng)絡(luò)請求從遠(yuǎn)程服務(wù)器獲取一些資源(例如,文本文件、圖像文件、二進(jìn)制文件等)。
為了處理這些情況,必須編寫異步代碼,而回調(diào)函數(shù)是處理這些情況的一種方法。所以從本質(zhì)上上說,回調(diào)函數(shù)是異步的。
當(dāng)多個異步函數(shù)一個接一個地執(zhí)行時,會產(chǎn)生回調(diào)地獄。它也被稱為厄運(yùn)金字塔。
假設(shè)你要獲取所有 Github 用戶的列表。然后在用戶中搜索 JavaScript 庫的主要貢獻(xiàn)者。再然后,你想要在用戶中獲取姓名為 John 的人員的詳細(xì)信息。
為了在回調(diào)的幫助下實(shí)現(xiàn)這個功能,代碼應(yīng)該如下所示:
http.get('https://api.github.com/users', function(users) { /* Display all users */ console.log(users); http.get('https://api.github.com/repos/javascript/contributors?q=contributions&order=desc', function(contributors) { /* Display all top contributors */ console.log(contributors); http.get('https://api.github.com/users/Jhon', function(userData) { /* Display user with username 'Jhon' */ console.log(userData); }); }); });
從上面的代碼片段中,你可以看到代碼變得更加難以理解,以及難以維護(hù)和修改。這是由回調(diào)函數(shù)的嵌套而引發(fā)的。
可以使用多種技術(shù)來避免回調(diào)地獄,如下所示。
使用promise
借助 async-await
使用 async.js 庫
讓我們談?wù)勗鯓佑?async.js 庫避免回調(diào)地獄。
根據(jù) async.js 官方網(wǎng)站的描述:Async 是一個工具模塊,它提供了直接、強(qiáng)大的函數(shù)來使用異步 JavaScript。
Async.js 總共提供約 70 個函數(shù)?,F(xiàn)在,我們將僅討論其中兩個,即 async.waterfall() 和 async.series()。
當(dāng)你要一個接一個地運(yùn)行某些任務(wù),然后將結(jié)果從上一個任務(wù)傳到下一個任務(wù)時,這個函數(shù)非常有用。它需要一個函數(shù)“任務(wù)”數(shù)組和一個最終的“回調(diào)”函數(shù),它會在“任務(wù)”數(shù)組中所有的函數(shù)完成后,或者用錯誤對象調(diào)用“回調(diào)”之后被調(diào)用。
var async = require('async'); async.waterfall([ function(callback) { /* Here, the first argument value is null, it indicates that the next function will be executed from the array of functions. If the value was true or any string then final callback function will be executed, other remaining functions in the array will not be executed. */ callback(null, 'one', 'two'); }, function(param1, param2, callback) { // param1 now equals 'one' and param2 now equals 'two' callback(null, 'three'); }, function(param1, callback) { // param1 now equals 'three' callback(null, 'done'); } ], function (err, result) { /* This is the final callback function. result now equals 'done' */ });
當(dāng)你要運(yùn)行一個函數(shù)然后在所有函數(shù)成功執(zhí)行后需要獲取結(jié)果時,它很有用。 async.waterfall() 和 async.series() 之間的主要區(qū)別在于, async.series() 不會將數(shù)據(jù)從一個函數(shù)傳遞到另一個函數(shù)。
async.series([ function(callback) { // do some stuff ... callback(null, 'one'); }, function(callback) { // do some more stuff ... callback(null, 'two'); } ], // optional callback function(err, results) { // results is now equal to ['one', 'two'] });
用技術(shù)術(shù)語來說,閉包是捆綁在一起的函數(shù)的組合,引用了其周圍的狀態(tài)。
簡而言之,閉包允許從內(nèi)部函數(shù)訪問外部函數(shù)的作用域。
要使用閉包,我們需要在一個函數(shù)內(nèi)部定義另一個函數(shù)。然后,我們需要將其返回或傳給另一個函數(shù)。
從概念上講,回調(diào)類似于閉包?;卣{(diào)基本上是把一個函數(shù)作為另一個函數(shù)的用法。
感謝各位的閱讀!關(guān)于“JavaScript回調(diào)函數(shù)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。