成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【譯】理解回調(diào)和Promise

liuyix / 2567人閱讀

摘要:理解回調(diào)和原文自工程師博客,傳送門這兩個概念是編程語言的基本內(nèi)容?;卣{(diào)地獄就是濫用回調(diào)。通常,在回調(diào)中,錯誤作為第一個參數(shù)傳遞。這個具有這兩個函數(shù)作為參數(shù)的回調(diào)稱為執(zhí)行程序。到目前為止,我希望我已經(jīng)讓自己了解了回調(diào)和。

理解回調(diào)和Promise
原文自工程師Fernando Hernandez博客,傳送門

這兩個概念是Javascript編程語言的基本內(nèi)容。因為這種語言是在異步編程的范例下工作。

所以,我決定分享這篇文章,以便了解這兩個用來執(zhí)行異步操作的特性——回調(diào)和Promise是什么。

那么,我們開始吧!

回調(diào)

為了理解回調(diào),我將做一個簡短的比喻。

假設(shè)我們正在通電話。在談話時,出現(xiàn)了需要立即解決的情況。我們把電話掛了,我們先做需要立即解決的事情,當(dāng)我們完成時,我們再回到我們剛剛暫停的電話。

好吧,通過這個例子,我們可以大致了解什么是回調(diào)。

現(xiàn)在,用編程語言說。

回調(diào)是在異步操作已經(jīng)完成后將要執(zhí)行的功能。

回調(diào)作為參數(shù)傳遞給異步操作。通常,是作為函數(shù)的最后一個參數(shù)傳遞的。這樣做是一種很好的做法,所以請記住這一點。

回調(diào)的結(jié)構(gòu)如下所示:

function sayHello() {
    console.log("Hello everyone");
}

setTimeout(()=>{sayHello()}, 3000);

我們在上面的例子中所做的是,首先定義一個向控制臺輸出消息的函數(shù)。之后,我們使用一個名為setTimeout的計時器(此計時器是一個本機Javascript函數(shù))。此計時器是一個異步操作,在一定時間后執(zhí)行回調(diào)。在這個例子中,在3000ms(3秒)之后將執(zhí)行sayHello函數(shù)。

回調(diào)模式

正如我們在開始時提到的那樣,作為優(yōu)秀的開發(fā)人員,我們應(yīng)該將回調(diào)位置視為參數(shù)。應(yīng)始終將其作為最后一個。這就是回調(diào)模式的名稱。

通過這種方式,我們的代碼將更具可讀性,并且當(dāng)其他程序員處理它時將更容易維護。

我們來看另一個回調(diào)示例:

const fs = require("fs") // Importing Nodejs library

// Declaring file path
const filePath = "./users.json"

// Asynchronous operation to read the file
fs.readFile(filePath, function onReadFile(err, result) {
    // In case of error print it in the console
    if (err) {
        console.log("There was an error: " + err)
        return // Get out of the function
    }
    // Print on the console the file and the content of it.
    console.log("The file was successfully read it: " + result)
})

在這里,我們使用Nodejs庫,用于在我們的文件系統(tǒng)上進行操作。在該示例中,我們使用readFile函數(shù)來從我們的計算機中讀取文件。此函數(shù)接收兩個參數(shù)(文件路徑和回調(diào))。我們可以注意到,名為onReadFile的回調(diào)它是最后一個參數(shù)。

匿名聲明回調(diào)是很常見的,但是如果會出現(xiàn)錯誤的情況,最好為它指定一個名稱,以便更容易地識別它。

最后,直到我們的代碼完成讀取所請求的文件將會執(zhí)行該回調(diào)。如果存在,Javascript將在此過程中繼續(xù)執(zhí)行代碼。

回調(diào)地獄

一旦你知道回調(diào)函數(shù)是如何工作的,并付諸實踐,我們就必須記住一些東西。作為一名優(yōu)秀的開發(fā)人員,我們必須知道如何使用它,并避免像回調(diào)地獄這樣糟糕的事情。

回調(diào)地獄就是濫用回調(diào)。 它看起來像這樣:

fs.readdir(source, function (err, files) {
  if (err) {
    console.log("Error finding files: " + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      console.log(filename)
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.log("Error identifying file size: " + err)
        } else {
          console.log(filename + " : " + values)
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            console.log("resizing " + filename + "to " + height + "x" + height)
            this.resize(width, height).write(dest + "w" + width + "_" + filename,             function(err) {
              if (err) console.log("Error writing file: " + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

基本上,我們可以看到,使用嵌套回調(diào)是一種不好的做法,它會在視覺上產(chǎn)生一種金字塔式的效果。這將成為難以維護和讀取的代碼,我們不希望這樣。

如何避免回調(diào)地獄?

命名函數(shù):正如我之前所說,你可以做的第一件事是命名你的函數(shù)(回調(diào))。因此,當(dāng)發(fā)生錯誤時,它將使用函數(shù)名稱以特定方式指示錯誤。此外,這會使你的代碼更具可讀性,當(dāng)其他程序員閱讀時,它們更容易維護它。

模塊化:一旦命名了函數(shù),就可以開始多帶帶定義它們。這樣,您將只用輸入回調(diào)名稱。首先,可以在同一文件底部定義它們。除此之外,另一種方法是將該函數(shù)寫入多帶帶的文件。這樣,我們可以在任何文件中導(dǎo)出和導(dǎo)入它。

這使得我們代碼更具有可重用性,有更高的可讀性和易維護性。

處理錯誤:編寫代碼時,我們必須記住錯誤總是會發(fā)生。為了能夠輕松地識別定位它們,編寫處理可能發(fā)生的錯誤的代碼非常重要。

通常,在回調(diào)中,錯誤作為第一個參數(shù)傳遞。我們可以通過以下方式處理錯誤:

const fs = require("fs")

const filePath = "./users.json"

fs.readFile(filePath, handleFile)

function handleFile(err, result) {
    if (err) {
        return console.log("There was an error: " + err)
    }
    console.log("File: " + result)
}

養(yǎng)成良好的編程習(xí)慣,讓其余程序員不會恨你一輩子!

Promise

Javascript中的Promise就是相當(dāng)于字面意思上的承諾。我們知道,當(dāng)我們做出承諾時,這意味著我們將盡一切可能實現(xiàn)預(yù)期的結(jié)果。但是,我們也知道,由于某種原因,不能總是履行承諾。

正如承諾在現(xiàn)實生活中一樣,它是在Javascript中,則另一種方式表示即代碼。

讓我們看一個Promise的例子:

let promise = new Promise(function(resolve, reject) {
    // things to do to accomplish your promise

    if(/* everything turned out fine */) {
        resolve("Stuff worked")
    } else { // for some reason the promise doesn"t fulfilled
        reject(new Error("it broke"))
    }
})

Promise是Javascript的原生類(自ES6起)。

promise的構(gòu)造函數(shù)接收一個參數(shù):一個回調(diào),它有兩個參數(shù):

resolve

reject

這些是已經(jīng)在Javascript中定義的函數(shù),因此我們不用自己去構(gòu)建它們。

這個具有這兩個函數(shù)作為參數(shù)的回調(diào)稱為執(zhí)行程序。

執(zhí)行者在創(chuàng)建承諾時立即運行。

執(zhí)行函數(shù)將執(zhí)行什么?

好吧,在這里面,我們將放置所有必要的代碼來實現(xiàn)我們的承諾。

一旦執(zhí)行程序完成執(zhí)行,我們將發(fā)送其中一個函數(shù)作為參數(shù)。

如果實現(xiàn)了,我們使用resolve函數(shù)。

如果由于某種原因失敗,我們使用reject函數(shù)。

函數(shù)resolve和reject,只接收一個參數(shù)。reject函數(shù)通常會使用Error類傳遞錯誤,正如我們在前面的示例中所看到的那樣。

Promise有三個獨特的狀態(tài):

Pending:異步操作尚未完成。

Fulfilled:異步操作已完成并返回一個值。

Rejected:指示異步操作失敗以及失敗的原因。

Promise對象有兩個屬性:

State:表示Promise的狀態(tài)。

Result:存儲Promise的值(如果已滿足)或錯誤(如果已拒絕)。

最初,Promise的狀態(tài)為“pending”,結(jié)果為“undefined”。

一旦promise完成執(zhí)行,promise的狀態(tài)和結(jié)果將被修改為相應(yīng)的值。取決于promise是否已完成或被拒絕。

讓我們看看下面的圖表來更好地理解它:

一旦promise改變了他們的狀態(tài),他們就無法逆轉(zhuǎn)。

如何使用或調(diào)用Promise?

為了使用我們創(chuàng)建的Promise,我們使用then和catch函數(shù)。在代碼中,它們看起來像這樣:

promise.then(function(result) {
    console.log(result)
}).catch(function(err) {
    console.log(err)
})

then允許我們處理已完成或已執(zhí)行狀態(tài)的promise

函數(shù)catch將允許我們處理被拒絕狀態(tài)的promise

在then函數(shù)中,我們也可以處理被拒絕的promise。為此,處理程序接收兩個參數(shù)。第一個是已完成的promise,第二個是被拒絕的promise。通過這種方式:

promise.then(function(result) { // Handling the value
    console.log(result)
}, function(err) { // Handling the error
    console.log(err)
})

處理程序then和catch都是異步的。

基本上,一旦Javascript執(zhí)行了下面的代碼,就會執(zhí)行then和catch。

例:

promise.then(function(result) {
    console.log(result)
}).catch(function(err) {
    console.log(err)
})

console.log("Hello world")

我們可能認為首先它會先在控制臺輸出在promise中的value或error。但是要知道它們是異步操作,我們必須記住它將花費最少的時間來執(zhí)行,因此消息“Hello world”還是會首先顯示。
Promise類有一個名為all的方法,用于執(zhí)行promise數(shù)組。它看起來像這樣:

Promise.all([
    new Promise.((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
    new Promise.((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
    new Promise.((resolve, reject) => setTimeout(() => resolve(3), 1000)), // 3
]).then(result => console.log(result)) // 1, 2, 3

在隨后處理程序?qū)⒃诳刂婆_輸出每個promise的結(jié)果的數(shù)組。
如果其中一個promise被reject,則該函數(shù)將被reject并出現(xiàn)錯誤。如下所示:

Promise.all([
    new Promise.((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
    new Promise.((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
    new Promise.((resolve, reject) => setTimeout(() => reject(new Error("An error has ocurred")), 1000))
]).then(result => console.log(result))
.catch(err => console.log(err)) // An error has ocurred

還有另一種類似于all的方法,但又有所不同。它是race方法。
與all函數(shù)相同,它接收一個promise數(shù)組,但它將返回先完成或拒絕的promise。我們來看一個代碼示例:

let promise1 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("promise one")
    }, 3000) // Resolve after 3 seconds
})

let promise2 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("promise two")
    }, 1000) // Resolve after 1 seconds
})

Promise.race([
    promise1,
    promise2
]).then(result => console.log(result)) // promise two

我們可以看到,返回給我們的值是第二個promise返回的。這是因為第一個promise是先執(zhí)行的。
讓我們看一個被拒絕的promise的另一個例子:

let promise1 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("promise one")
    }, 3000) // Resolve after 3 seconds
})

let promise2 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("promise two")
    }, 2000) // Resolve after 2 seconds
})

let promise3 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        reject("promise three rejected")
    }, 1000) // Reject after 1 second
})

Promise.race([
    promise1,
    promise2,
    promise3
]).then(result => console.log(result))
.catch(err => console.log(err)) // promise three is rejected

在這段代碼race函數(shù)中,將要打印的是在我們聲明的第三個promise中發(fā)現(xiàn)的錯誤。你可以想象得到為什么。實際上,第三個promise比其他promise先執(zhí)行。

因此,無論promise是否被拒絕或完成,race方法將執(zhí)行第一個并忽略其他方法。

到目前為止,我希望我已經(jīng)讓自己了解了回調(diào)和promise?;旧?,Javascript的這兩個特性用于處理異步操作。這就是這門語言的基礎(chǔ),因此它很受歡迎。

我將很快繼續(xù)關(guān)于處理異步的另一篇文章——Async-Await。

譯者總結(jié)

本文是小編的第一次譯文,翻譯不到位請見諒。由于突然想重溫一下Promise,為此對Promise的知識點進行了再次溫故,看看從不同人的角度怎么去理解Promise的。上文對Promise進行了簡單的介紹并附帶一些回調(diào)的知識點,也讓我對回調(diào)有了新的見解。相信對讀者也會有所幫助,我會再接再厲的!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101823.html

相關(guān)文章

  • [] 深入理解 Promise 五部曲:2. 控制權(quán)轉(zhuǎn)換問題

    摘要:直到最近,我們?nèi)匀辉谟煤唵蔚幕卣{(diào)函數(shù)來處理異步的問題。當(dāng)我們只有一個異步任務(wù)的時候使用回調(diào)函數(shù)看起來還不會有什么問題。 原文地址:http://blog.getify.com/promis... 廈門旅行歸來,繼續(xù)理解Promise 在上一篇深入理解Promise五部曲:1.異步問題中,我們揭示了JS的異步事件輪詢并發(fā)模型并且解釋了多任務(wù)是如何相互穿插使得它們看起來像是同時運行的。...

    alanoddsoff 評論0 收藏0
  • [] 深入理解 Promise 五部曲:1. 異步問題

    摘要:當(dāng)引擎開始執(zhí)行一個函數(shù)比如回調(diào)函數(shù)時,它就會把這個函數(shù)執(zhí)行完,也就是說只有執(zhí)行完這段代碼才會繼續(xù)執(zhí)行后面的代碼。當(dāng)條件允許時,回調(diào)函數(shù)就會被運行?,F(xiàn)在,返回去執(zhí)行注冊的那個回調(diào)函數(shù)。 原文地址:http://blog.getify.com/promis... 在微博上看到有人分享LabJS作者寫的關(guān)于Promise的博客,看了下覺得寫得很好,分五個部分講解了Promise的來龍去脈。從...

    CHENGKANG 評論0 收藏0
  • 理解Node事件驅(qū)動架構(gòu)

    摘要:回調(diào)方式將回調(diào)函數(shù)作為參數(shù)傳遞給主函數(shù),同時在主函數(shù)內(nèi)部處理錯誤信息。模塊是促進中對象之間交流的模塊,它是異步事件驅(qū)動機制的核心。在異步函數(shù)的回調(diào)中,根據(jù)執(zhí)行情況觸發(fā)或者事件。比如,當(dāng)異常事件觸發(fā)關(guān)閉數(shù)據(jù)庫的動作時。 原文鏈接:Understanding Nodejs Event-driven Architecture 作者:Samer Buna 翻譯:野草 本文首發(fā)于前端早讀課【...

    mrcode 評論0 收藏0
  • []理解 Node.js 事件驅(qū)動機制

    摘要:事件驅(qū)動機制的最簡單形式,是在中十分流行的回調(diào)函數(shù),例如。在回調(diào)函數(shù)這種形式中,事件每被觸發(fā)一次,回調(diào)就會被觸發(fā)一次?;卣{(diào)函數(shù)需要作為宿主函數(shù)的一個參數(shù)進行傳遞多個宿主回調(diào)進行嵌套就形成了回調(diào)地獄,而且錯誤和成功都只能在其中進行處理。 學(xué)習(xí) Node.js 一定要理解的內(nèi)容之一,文中主要涉及到了 EventEmitter 的使用和一些異步情況的處理,比較偏基礎(chǔ),值得一讀。 閱讀原文 大...

    Snailclimb 評論0 收藏0
  • JavaScript 異步

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個符合規(guī)范并可配合使用的寫一個符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個需求:在系統(tǒng)初始化時通過http獲取一個第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個接口,可通過...

    tuniutech 評論0 收藏0

發(fā)表評論

0條評論

liuyix

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<