老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

重慶分公司,新征程啟航

為企業(yè)提供網(wǎng)站建設(shè)、域名注冊、服務(wù)器等服務(wù)

javascript中的回調(diào)是什么

小編給大家分享一下javascript中的回調(diào)是什么,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計、成都做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、洪洞ssl等。為上千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的洪洞網(wǎng)站制作公司

你有無意中看到 "callback" 但并不知道其中的意思么?不用擔心。不是只有你一個人這樣。很多JavaScript 新手都難以理解回調(diào)。

雖然回調(diào)比較令人困惑,你仍然需要徹底的學(xué)習理解它們,因為它在 JavaScript 中是一個很關(guān)鍵的概念。如果你不知道回調(diào),那么你無法走的長遠。

這篇文章中你會看到 ES6 里的箭頭函數(shù)。如果你還不熟悉它們,我建議你先看看ES6 post。(只要閱讀箭頭函數(shù)部分)。

什么是回調(diào)?

回調(diào)是一個函數(shù),會作為一個參數(shù)傳遞到另一個函數(shù)中,并稍后去執(zhí)行。(開發(fā)人員說在執(zhí)行函數(shù)時調(diào)用另一個函數(shù),這就是為什么 callbacks 稱之為回調(diào)的原因)。

它們在 JavaScript 中很常見,以至于你可能不知道它們是回調(diào)函數(shù)的時候已經(jīng)使用過它們。

一個可以接收回調(diào)函數(shù)的例子是addEventLisnter

const button = document.querySelector('button')
button.addEventListener('click', function(e) {
    // Adds clicked class to button
    this.classList.add('clicked')
})

沒看出來這是個回調(diào)?來看看下個例子。

const button = document.querySelector('button')

// Function that adds 'clicked' class to the element
function clicked (e) {
    this.classList.add('clicked')
}

// Adds click function as a callback to the event listener
button.addEventListener('click', clicked)

這里,我們通過 JavaScript 給一個按鈕綁定了click事件。一旦檢測到了點擊時間,JavaScript 會執(zhí)行clicked函數(shù)。所以,在這個例子中,當addEventListener函數(shù)接收一個回調(diào)函數(shù)時,clicked是一個回調(diào)。

現(xiàn)在知道回調(diào)是什么了么?:)

我們來看看另外一個例子。這一次,我們假設(shè)你想過濾一個數(shù)字數(shù)組來得到一個小于5的列表。這里,你給filter函數(shù)傳遞了一個回調(diào)函數(shù)。

const numbers = [3, 4, 10, 20]
const lesserThanFive = numbers.filter(num => num < 5)

現(xiàn)在,如果你把上面的代碼用具名函數(shù)改一下,那么過濾數(shù)組就會變成這樣:

const numbers = [3, 4, 10, 20]
const getLessThanFive = num => num < 5

// Passing getLessThanFive function into filter
const lesserThanFive = numbers.filter(getLessThanFive)

在這個例子中,getLessThanFive是個回調(diào)。Array.filter是一個可以接收回調(diào)的函數(shù)。

現(xiàn)在看看?當你知道回調(diào)后會發(fā)現(xiàn)無處不在。

下面這個例子告訴你怎么寫一個回調(diào)函數(shù)和一個可以接收回調(diào)的函數(shù)。

// Create a function that accepts another function as an argument
const callbackAcceptingFunction = (fn) => {
    // Calls the function with any required arguments
    return fn(1, 2, 3)
}

// Callback gets arguments from the above call
const callback = (arg1, arg2, arg3) => {
    return arg1 + arg2 + arg3
}

// Passing a callback into a callback accepting function
const result = callbackAcceptingFunction(callback)
console.log(result) // 6

請注意,當你把回調(diào)傳給另一個函數(shù)時,只是把引用傳遞過去了(不執(zhí)行,因此沒有()

`const result = callbackAcceptingFunction(callback)`

你只能在callbackAcceptingFunction里調(diào)用這個回調(diào)當你這么做時,你可以給這個回調(diào)函數(shù)傳遞可能需要任意數(shù)量的參數(shù):

const callbackAcceptingFunction = (fn) => {
    // Calls the callback with three args
    fn(1, 2, 3)
}

這些參數(shù)通過callbackAcceptingFunction傳遞到回調(diào)里,然后用它們的方式在回調(diào)里進行傳遞:

// Callback gets arguments from callbackAcceptingFunction
const callback = (arg1, arg2, arg3) => {
    return arg1 + arg2 + arg3
}

這是一個回調(diào)的結(jié)構(gòu)。現(xiàn)在,你知道了addEventListener包含了event參數(shù):

// Now you know where this event object comes from! :)
button.addEventListener('click', (event) => {
    event.preventDefault()
})

??!這是回調(diào)的基本含義!只要記住關(guān)鍵字:將一個函數(shù)傳遞到另一個函數(shù)中,你將回想起上面提到的機制。

這種傳遞函數(shù)的能力是一個很大的事情。它是如此之大,以至于 JavaScript 中的函數(shù)都是高階函數(shù)。高階函數(shù)是函數(shù)式編程范式中非常重要的東西。

但我們現(xiàn)在并不討論這個話題?,F(xiàn)在,我確信你已經(jīng)知道了回調(diào)以及如何使用了。但是,你為什么需要使用回調(diào)呢?

為什么使用回調(diào)?

回調(diào)有二種不同的使用方式 - 在同步函數(shù)和在異步函數(shù)中。

同步函數(shù)中的回調(diào)

如果你的代碼執(zhí)行是一個從上到下,從做到右的方式,順序地,在下一行代碼執(zhí)行前會等到代碼執(zhí)行完成,那么你的代碼是同步的。

我們來看個例子,以便于更早的理解:

const addOne = (n) => n + 1
addOne(1) // 2
addOne(2) // 3
addOne(3) // 4
addOne(4) // 5

在上面的例子中,addOne(1)先執(zhí)行。當執(zhí)行完成時,addOne(2)開始執(zhí)行。當addOne(2)執(zhí)行完成時,addOne(3)開始執(zhí)行。這個過程一直執(zhí)行到最后一行代碼被執(zhí)行。

但你想讓一部分代碼跟其他交換簡單時,這時候可以在同步的函數(shù)里使用回調(diào)。

所以,回到上面的Array.filter例子,雖然過濾數(shù)組讓其包含小于5的數(shù)字,同樣地你也可以復(fù)用Array.filter去包含大于10 的數(shù)字。

const numbers = [3, 4, 10, 20]
const getLessThanFive = num => num < 5
const getMoreThanTen = num => num > 10

// Passing getLessThanFive function into filter
const lesserThanFive = numbers.filter(getLessThanFive)

// Passing getMoreThanTen function into filter
const moreThanTen = numbers.filter(getMoreThanTen)

這是你為什么在同步函數(shù)中使用回調(diào)?,F(xiàn)在,讓我們繼續(xù)看看為什么我們在異步函數(shù)里使用回調(diào)。

異步函數(shù)里的回調(diào)

這里異步的意思是,如果 JavaScript 需要等待某個東西完成,在等待的過程中會執(zhí)行其余的任務(wù)。

一個異步函數(shù)例子就是setTimeout。它會一段時間后執(zhí)行回調(diào)函數(shù)。

// Calls the callback after 1 second
setTimeout(callback, 1000)

如果你給JavaScript 另一個任務(wù)去完成時我們看看setTimeout是怎么工作的:

const tenSecondsLater = _ = > console.log('10 seconds passed!')

setTimeout(tenSecondsLater, 10000)
console.log('Start!')

在上面的代碼里,JavaScript 去執(zhí)行setTimeout。這時,會等待10秒且打印日志“10 seconds passed!”。

同時,在等到10秒去執(zhí)行setTimeout時,JavaScript 會執(zhí)行console.log("Start!")

因此,如果你記錄上面的代碼,你會看到這一點。

// What happens:
// > Start! (almost immediately)
// > 10 seconds passed! (after ten seconds)

啊。異步操作聽起來很復(fù)雜,不是么?但是我們?yōu)槭裁丛?JavaScript 里到處使用呢?

要理解為什么異步操作很重要,想象一下 JavaScript 是你家里的一個機器人助手。這個助手很蠢。一次只能做一件事情。(這個行為稱之為單線程)。

假設(shè)你告訴機器人助手幫你訂點披薩。但是機器人助手如此蠢,在給披薩店打完電話后,機器人助手坐在你家門前,慢慢的等待披薩送來。在這個過程中不能做任何其他的事情。

等待的過程中,你不能讓它去熨燙衣服,拖地板以及其他任何事情。你需要等20分鐘,直到披薩送來,才愿意做其他的事情。

這個行為稱之為阻塞。在等待一個任務(wù)執(zhí)行完全之前,其他的操作被阻止了。

const orderPizza = flavour => {
    callPizzaShop(`I want a ${flavour} pizza`)
    waits20minsForPizzaToCome() // Nothing else can happen here
    bringPizzaToYou()
}

orderPizza('Hawaiian')

// These two only starts after orderPizza is completed
mopFloor()
ironClothes()

現(xiàn)在,阻塞操作是非常令人失望的。

為什么?

我們把愚蠢的機器人助手放在瀏覽器的運行環(huán)境里。想象一下,當按鈕被點擊時需要改變按鈕的顏色。

那這個愚蠢的機器人會怎么做呢?

它會凝視著這個按鈕,在按鈕被點擊之前,忽略掉其他任何的命令。同時,用戶不能選擇其他任何東西。看看現(xiàn)在這樣的情況?這就是異步編程在 JavaScript 為什么如此重要。

但是真正理解在異步操作過程中發(fā)生了什么,我們需要理解另外一個東西-事件循環(huán)。

事件循環(huán)

想象事件循環(huán),可以想象 JavaScript 是一個 todo-list 的管家。這個列表包含了所有你告訴它的事情。JavaScript 會按照你給的順序,一步步的遍歷這個列表。

假設(shè)你給JavaScript 的5個命令如下:

const addOne = (n) => n + 1

addOne(1) // 2
addOne(2) // 3
addOne(3) // 4
addOne(4) // 5
addOne(5) // 6

這將會出現(xiàn)在 JavaScript 的todo 列表里。

javascript中的回調(diào)是什么

命令在 JavaScript 的 todo 列表里同步顯示。

除了 todo 列表,JavaScript 還保存了一個 waiting 列表,這個列表可以跟蹤需要等待的東西。如果你告訴 JavaScript 需要定披薩,它會給披薩店打電話,并把"等待披薩送來"加到等到列表里。同時,它會做 todo 列表已經(jīng)有的事情。

所以,想象一下有這樣的代碼。

const orderPizza (flavor, callback) {
    callPizzaShop(`I want a ${flavor} pizza`)
    // Note: these three lines is pseudo code, not actual JavaScript
    whenPizzaComesBack {
        callback()
    }
}

const layTheTable = _ => console.log('laying the table')

orderPizza('Hawaiian', layTheTable)
mopFloor()
ironClothes()

JavaScript 的初始列表將會是:

javascript中的回調(diào)是什么

定披薩,拖地和熨燙衣服!

這是,當執(zhí)行到orderPizza,JavaScript 知道需要等待披薩送來。因此,在把"等待披薩送來"加到等待列表中的同時會處理剩下的工作。

javascript中的回調(diào)是什么

JavaScript 等待披薩到達。

當披薩送到時,按門鈴會通知 JavaScript并做一個標記,當處理完其他雜事時,會去執(zhí)行layTheTable。

javascript中的回調(diào)是什么

JavaScript 知道通過標記里的命令需要去執(zhí)行layTheTable

然后,一旦處理完了其他的雜務(wù),JavaScript 就會執(zhí)行回調(diào)函數(shù)layTheTable。

javascript中的回調(diào)是什么

當其他一切都完成時, JavaScript 會將其放置。

這就是我的朋友,事件循環(huán)。你可以用事件循環(huán)中的實際關(guān)鍵字來替代我們的巴特勒類比來理解所有的事情。

  • Todo-list-> Call stack

  • Waiting-list-> Web apis

  • Mental note-> Event queue

javascript中的回調(diào)是什么

JavaScript 事件循環(huán)

如果你有20分鐘空閑時間的話,我強烈推薦你看Philip Roberts在 JSConf 上關(guān)于事件循環(huán)的演講。它會幫助你了解事件循環(huán)里的細節(jié)。

為什么回調(diào)如此重要?

哦。我們在事件循環(huán)上轉(zhuǎn)了個大圈?,F(xiàn)在我們回頭來看。

之前,我們提到如果 JavaScript 專注地盯著一個按鈕并忽略其他所有的命令,這是非常糟糕的。是吧?

通過異步回調(diào),我們可以提前給 JavaScript 指令而不需要停止整個操作。

現(xiàn)在,當你讓 JavaScript 監(jiān)聽一個按鈕的點擊事件時,它將"監(jiān)聽按鈕"放在等待列表里,然后繼續(xù)做家務(wù)。當按鈕最終獲取到點擊事件時,JavaScript 會激活回調(diào),然后繼續(xù)運行

下面是一些常見的回調(diào)函數(shù),告訴 JavaScript 應(yīng)該怎么做:

  • 當事件被觸發(fā)(比如:addEventListener

  • Ajax 執(zhí)行之后(比如:jQuery.ajax

  • 文件讀寫之后(比如:fs.readFile)

// Callbacks in event listeners
document.addEventListener(button, highlightTheButton)
document.removeEventListener(button, highlightTheButton)

// Callbacks in jQuery's ajax method
$.ajax('some-url', {
    success (data) { /* success callback */ },
    error (err) { /* error callback */}
});

// Callbacks in Node
fs.readFile('pathToDirectory', (err, data) => {
    if (err) throw err
    console.log(data)
})

// Callbacks in ExpressJS
app.get('/', (req, res) => res.sendFile(index.html))

這就是回調(diào)!

希望,你現(xiàn)在已經(jīng)弄清楚了回調(diào)是什么并且怎么去使用。在最開始的時候,你沒必要創(chuàng)建很多的回調(diào),更多的去專注于學(xué)習如何使用可用的回調(diào)函數(shù)。

現(xiàn)在,在結(jié)束之前,我們來看看回調(diào)的第一個問題 - 回調(diào)地獄

回調(diào)地獄

回調(diào)地獄是在多個回調(diào)嵌套出現(xiàn)時的一個現(xiàn)象。它發(fā)生在一個異步回調(diào)執(zhí)行依賴上一個異步回調(diào)執(zhí)行的時候。這些嵌套的回調(diào)會導(dǎo)致代碼非常難以理解。

在我的經(jīng)驗里,你只會在 Node.js 里看到回調(diào)地獄。當你的 JavaScript 在前臺運行時一般都不會遇到回調(diào)地獄。

這里有一個回調(diào)地獄的例子:

// Look at three layers of callback in this code!
app.get('/', function (req, res) {
    Users.findOne({ _id:req.body.id }, function (err, user) {
        if (user) {
            user.update({/* params to update */}, function (err, document) {
            res.json({user: document})
        })
        } else {
            user.create(req.body, function(err, document) {
                res.json({user: document})
            })
        }
     })
})

現(xiàn)在,對你來說,解讀上面的代碼是一個挑戰(zhàn)。相當?shù)碾y,不是么?難怪在看到嵌套回調(diào)時,開發(fā)人員會不寒而栗。

解決回調(diào)的一個解決方案是將回調(diào)函數(shù)分解成更小的部分,以減少嵌套代碼的數(shù)量

const updateUser = (req, res) => {
    user.update({/* params to update */}, function () {
        if (err) throw err;
        return res.json(user)
    })
}

const createUser = (req, res, err, user) => {
    user.create(req.body, function(err, user) {
        res.json(user)
    })
}

app.get('/', function (req, res) {
    Users.findOne({ _id:req.body.id }, (err, user) => {
        if (err) throw err
        if (user) {
            updateUser(req, res)
        } else {
            createUser(req, res)
        }
    })
})

閱讀起來容易得多,不是么?

在新的JavaScript 版本里,還有一些新的解決回調(diào)地獄的方法,比如: promisesasync/await。但是,會在另一個話題中解析它們。

看完了這篇文章,相信你對javascript中的回調(diào)是什么有了一定的了解,想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


本文標題:javascript中的回調(diào)是什么
網(wǎng)站URL:http://www.xueling.net.cn/article/gceodj.html

其他資訊

在線咨詢
服務(wù)熱線
服務(wù)熱線:028-86922220
TOP
主站蜘蛛池模板: 中日韩亚洲人成无码网站 | 日本成本人片视频免费 | 91欧美一区二区三区 | 精品一区二区三区成人精品 | 国产精品Ⅴ无码大片在线看 | 日本熟妇毛茸茸XXXXX | 亚洲精品一区二区三区蜜桃久 | 少妇高潮大叫好爽 | 亚洲色成人四虎在线观看 | 这里只有精品国产 | 国产在线视频欧美一区 | 不卡在线一区2区三区 | 国产精品无码翘臀在线京东 | 免费a级毛片无码a∨ | 欧美激情一区二区三区AA片 | 久久av动漫 | 国产一区不卡视频 | 99国产精品热久久久久久 | 特级片在线免费观看 | 黄色一区二区三区四区 | 青青青草网站免费视频在线观看 | 精品熟女日韩中文十区 | 人人妻人人插视频 | 国产精品私密保养 | 日韩在线观看视频一区 | 亚州日本乱码一区二区三区 | 日本岛国片在线观看一区二区 | 99re中文在线视频 | 国精品人妻无码一区二区三区软件 | 一级黄免费看 | 桃色视频m3u8| 草草影院2022成人免费视频 | 東热精品中字久久无码五月天 | 成人性生活大片100部 | 国产亚洲精品久久久久久无几年桃 | 成年女人免费视频播放体验区 | 欧美成免费A级毛片 | 免费a级毛片在线播放 | 麻豆成人精品 | 成年人黄色片免费看 | 一本大道精品视频在线 |