国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

《深入理解ES6》筆記—— Promise與異步編程(11)

YacaToy / 2659人閱讀

摘要:為什么要異步編程我們?cè)趯?xiě)前端代碼時(shí),經(jīng)常會(huì)對(duì)做事件處理操作,比如點(diǎn)擊激活焦點(diǎn)失去焦點(diǎn)等再比如我們用請(qǐng)求數(shù)據(jù),使用回調(diào)函數(shù)獲取返回值。這些都屬于異步編程?;卣{(diào)有多個(gè)狀態(tài),當(dāng)響應(yīng)成功和失敗都有不同的回調(diào)函數(shù)。

為什么要異步編程

我們?cè)趯?xiě)前端代碼時(shí),經(jīng)常會(huì)對(duì)dom做事件處理操作,比如點(diǎn)擊、激活焦點(diǎn)、失去焦點(diǎn)等;再比如我們用ajax請(qǐng)求數(shù)據(jù),使用回調(diào)函數(shù)獲取返回值。這些都屬于異步編程。

也許你已經(jīng)大概知道JavaScript引擎單線程的概念,那么這種單線程模式和異步編程有什么關(guān)系呢?

JavaScript引擎中,只有一個(gè)主線程,當(dāng)執(zhí)行JavaScript代碼塊時(shí),不允許其他代碼塊執(zhí)行,而事件機(jī)制和回調(diào)機(jī)制的代碼塊會(huì)被添加到任務(wù)隊(duì)列(或者叫做堆棧)中,當(dāng)符合某個(gè)觸發(fā)回調(diào)或者事件的時(shí)候,就會(huì)執(zhí)行該事件或者回調(diào)函數(shù)。

上面這段話的意思可以這樣理解,假設(shè)你是一個(gè)修仙者,你去闖一個(gè)秘境,這個(gè)秘境就是主線程,你只能一直深入下去,直到找到寶物和出口,而你還有一個(gè)自身的儲(chǔ)物空間,這個(gè)空間就類似堆棧,你在儲(chǔ)物空間放了很多你可能用到的法寶或者丹藥,這些東西就是回調(diào)函數(shù)和事件函數(shù),當(dāng)你遇到危險(xiǎn)或者滿足某個(gè)條件時(shí),就可以從儲(chǔ)物空間拿出你當(dāng)前需要的東西。

好吧,不扯這么遠(yuǎn),下面看正題。

事件模型:
瀏覽器初次渲染DOM的時(shí)候,我們會(huì)給一些DOM綁定事件函數(shù),只有當(dāng)觸發(fā)了這些DOM事件函數(shù),才會(huì)執(zhí)行他們。

const btn = document.querySelector(".button")
btn.onclick = function(event) {
  console.log(event)
}

回調(diào)模式:
nodejs中可能非常常見(jiàn)這種回調(diào)模式,但是對(duì)于前端來(lái)說(shuō),ajax的回調(diào)是最熟悉不過(guò)了。ajax回調(diào)有多個(gè)狀態(tài),當(dāng)響應(yīng)成功和失敗都有不同的回調(diào)函數(shù)。

$.post("/router", function(data) {
  console.log(data)
})

回調(diào)也可能帶來(lái)一個(gè)問(wèn)題,那就是地獄回調(diào),不過(guò)幸運(yùn)的是,我從進(jìn)入前端界開(kāi)始,就使用react,跳過(guò)了很多坑,特別是地獄回調(diào),一直沒(méi)有機(jī)會(huì)在工作中遇見(jiàn)到,真是遺憾。

Promise

事件函數(shù)沒(méi)有問(wèn)題,我們用的很爽,問(wèn)題出在回調(diào)函數(shù),尤其是指地獄回調(diào),Promise的出現(xiàn)正是為了避免地獄回調(diào)帶來(lái)的困擾。

推薦你看JavaScript MDN Promise教程,然后再結(jié)合本文看,你就能學(xué)會(huì)使用Promise了。

Promise是什么

Promise的中文意思是承諾,也就是說(shuō),JavaScript對(duì)你許下一個(gè)承諾,會(huì)在未來(lái)某個(gè)時(shí)刻兌現(xiàn)承諾。

Promise生命周期

react有生命周期,vue也有生命周期,就連Promise也有生命周期,現(xiàn)在生命周期咋這么流行了。

Promise的生命周期:進(jìn)行中(pending),已經(jīng)完成(fulfilled),拒絕(rejected)

Promise被稱作異步結(jié)果的占位符,它不能直接返回異步函數(shù)的執(zhí)行結(jié)果,需要使用then(),當(dāng)獲取異?;卣{(diào)的時(shí)候,使用catch()。

這次我們使用axios插件的代碼做例子。axios是前端比較熱門(mén)的http請(qǐng)求插件之一。

1、創(chuàng)建axios實(shí)例instance。

import axios from "axios"
export const instance = axios.create()

2、使用axios實(shí)例 + Promise獲取返回值。

const promise = instance.get("url")

promise.then(result => console.log(result)).catch(err => console.log(err))
使用Promise構(gòu)建函數(shù)創(chuàng)建新的Promise

Promise構(gòu)造函數(shù)只有一個(gè)參數(shù),該參數(shù)是一個(gè)函數(shù),被稱作執(zhí)行器,執(zhí)行器有2個(gè)參數(shù),分別是resolve()和reject(),一個(gè)表示成功的回調(diào),一個(gè)表示失敗的回調(diào)。

new Promise(function(resolve, reject) {
  setTimeout(() => resolve(5), 0)
}).then(v => console.log(v)) // 5

記住,Promise實(shí)例只能通過(guò)resolve或者reject函數(shù)來(lái)返回,并且使用then()或者catch()獲取,不能在new Promise里面直接return,這樣是獲取不到Promise返回值的。

1、我們也可以使用Promise直接resolve(value)。

Promise.resolve(5).then(v => console.log(v)) // 5

2、也可以使用reject(value)

Promise.reject(5).catch(v => console.log(v)) // 5

3、執(zhí)行器錯(cuò)誤通過(guò)catch捕捉。

new Promise(function(resolve, reject) {
  if(true) {
    throw new Error("error!!")
  }
}).catch(v => console.log(v.message)) // error!!
全局的Promise拒絕處理

不重要的內(nèi)容,不用細(xì)看。

這里涉及到nodejs環(huán)境和瀏覽器環(huán)境的全局,主要說(shuō)的是如果執(zhí)行了Promise.reject(),瀏覽器或者node環(huán)境并不會(huì)強(qiáng)制報(bào)錯(cuò),只有在你調(diào)用catch的時(shí)候,才能知道Promise被拒絕了。

這種行為就像是,你寫(xiě)了一個(gè)函數(shù),函數(shù)內(nèi)部有true和false兩種狀態(tài),而我們希望false的時(shí)候拋出錯(cuò)誤,但是在Promise中,并不能直接拋出錯(cuò)誤,無(wú)論P(yáng)romise是成功還是拒絕狀態(tài),你獲取Promise生命周期的方法只能通過(guò)then()和catch()。

nodejs環(huán)境:

node環(huán)境下有個(gè)對(duì)象叫做process,即使你沒(méi)寫(xiě)過(guò)后端node,如果寫(xiě)過(guò)前端node服務(wù)器,也應(yīng)該知道可以使用process.ENV_NODE獲取環(huán)境變量。為了監(jiān)聽(tīng)Promise的reject(拒絕)情況,NodeJS提供了一個(gè)process.on(),類似jQuery的on方法,事件綁定函數(shù)。

process.on()有2個(gè)事件

unhandledRjection:在一個(gè)事件循環(huán)中,當(dāng)Promise執(zhí)行reject(),并且沒(méi)有提供catch()時(shí)被調(diào)用。

正常情況下,你可以使用catch捕捉reject。

Promise.reject("It was my wrong!").catch(v => console.log(v))

但是,有時(shí)候你不總是記得使用catch。你就需要使用process.on()

let rejected
rejected = Promise.reject("It was my wrong!")

process.on("unhandledRjection", function(reason, promise) {
  console.log(reason.message) // It was my wrong!
  console.log(rejected === promise) // true
})

rejectionHandled:在一個(gè)事件循環(huán)后,當(dāng)Promise執(zhí)行reject,并且沒(méi)有提供catch()時(shí)被調(diào)用。

let rejected
rejected = Promise.reject(new Error("It was my wrong!"))

process.on("rejectionHandled", function(promise) {
  console.log(rejected === promise) // true
})

異同:

事件循環(huán)中、事件循環(huán)后,你可能很難理解這2個(gè)的區(qū)別,但是這不重要,重要的是,如果你通過(guò)了catch()方法來(lái)捕捉reject操作,那么,這2個(gè)事件就不會(huì)生效。

瀏覽器環(huán)境:

和node環(huán)境一樣,都提供了unhandledRjection、rejectionHandled事件,不同的是瀏覽器環(huán)境是通過(guò)window對(duì)象來(lái)定義事件函數(shù)。

let rejected
rejected = Promise.reject(new Error("It was my wrong!"))

window.rejectionHandled = function(event) {
  console.log(event) // true
}
rejectionHandled()

將代碼在瀏覽器控制臺(tái)執(zhí)行一遍,你就會(huì)發(fā)現(xiàn)報(bào)錯(cuò)了:Uncaught (in promise) Error: It was my wrong!

耶,你成功了!報(bào)錯(cuò)內(nèi)容正是你寫(xiě)的reject()方法里面的錯(cuò)誤提示。

Promise鏈?zhǔn)秸{(diào)用

這個(gè)例子中,使用了3個(gè)then,第一個(gè)then返回 s * s,第二個(gè)then捕獲到上一個(gè)then的返回值,最后一個(gè)then直接輸出end。這就叫鏈?zhǔn)秸{(diào)用,很好理解的。我只使用了then(),實(shí)際開(kāi)發(fā)中,你還應(yīng)該加上catch()。

new Promise(function(resolve, reject) {
try {

resolve(5)

} catch (error) {

reject("It was my wrong!!!")

}
}).then(s => s * s).then(s2 => console.log(s2)).then(() => console.log("end"))
// 25 "end"

Promise的其他方法

在Promise的構(gòu)造函數(shù)中,除了reject()和resolve()之外,還有2個(gè)方法,Promise.all()、Promise.race()。

Promise.all():

前面我們的例子都是只有一個(gè)Promise,現(xiàn)在我們使用all()方法包裝多個(gè)Promise實(shí)例。

語(yǔ)法很簡(jiǎn)單:參數(shù)只有一個(gè),可迭代對(duì)象,可以是數(shù)組,或者Symbol類型等。

Promise.all(iterable).then().catch()

示例:傳入3個(gè)Promise實(shí)例

Promise.all([
  new Promise(function(resolve, reject) {
    resolve(1)
  }),
  new Promise(function(resolve, reject) {
    resolve(2)
  }),
  new Promise(function(resolve, reject) {
    resolve(3)
  })
]).then(arr => {
  console.log(arr) // [1, 2, 3]
})

Promise.race():語(yǔ)法和all()一樣,但是返回值有所不同,race根據(jù)傳入的多個(gè)Promise實(shí)例,只要有一個(gè)實(shí)例resolve或者reject,就只返回該結(jié)果,其他實(shí)例不再執(zhí)行。

還是使用上面的例子,只是我給每個(gè)resolve加了一個(gè)定時(shí)器,最終結(jié)果返回的是3,因?yàn)榈谌齻€(gè)Promise最快執(zhí)行。

Promise.race([
  new Promise(function(resolve, reject) {
    setTimeout(() => resolve(1), 1000)
  }),
  new Promise(function(resolve, reject) {
    setTimeout(() => resolve(2), 100)
  }),
  new Promise(function(resolve, reject) {
    setTimeout(() => resolve(3), 10)
  })
]).then(value => {
  console.log(value) // 3
})
Promise派生

派生的意思是定義一個(gè)新的Promise對(duì)象,繼承Promise方法和屬性。

class MyPromise extends Promise {

  //重新封裝then()
  success(resolve, reject) {
    return this.then(resolve, reject)
  }
  //重新封裝catch()
  failer(reject) {
    return this.catch(reject)
  }
}

接著我們來(lái)使用一下這個(gè)派生類。

new MyPromise(function(resolve, reject) {
  resolve(10)
}).success(v => console.log(v)) // 10

如果只是派生出來(lái)和then、catch一樣的方法,我想,你不會(huì)干這么無(wú)聊的事情。

Promise和異步的聯(lián)系

Promise本身不是異步的,只有他的then()或者catch()方法才是異步,也可以說(shuō)Promise的返回值是異步的。通常Promise被使用在node,或者是前端的ajax請(qǐng)求、前端DOM渲染順序等地方。

比Promise更牛逼的異步方案

在本章你只需要了解有async這個(gè)未來(lái)的方案,推薦不會(huì)的趕緊去網(wǎng)上找資料學(xué),反正我是已經(jīng)在實(shí)際項(xiàng)目中全面開(kāi)展async了。

async function a() {
    await function() {}}
}
總結(jié)

Promise是什么、怎么用、怎么獲取返回值?是本章的中心內(nèi)容,多看幾遍,你會(huì)發(fā)現(xiàn)使用Promise是非常簡(jiǎn)單的事情。

=> 返回文章目錄

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/112331.html

相關(guān)文章

  • 深入理解ES6筆記—— Promise異步編程11

    摘要:為什么要異步編程我們?cè)趯?xiě)前端代碼時(shí),經(jīng)常會(huì)對(duì)做事件處理操作,比如點(diǎn)擊激活焦點(diǎn)失去焦點(diǎn)等再比如我們用請(qǐng)求數(shù)據(jù),使用回調(diào)函數(shù)獲取返回值。這些都屬于異步編程?;卣{(diào)有多個(gè)狀態(tài),當(dāng)響應(yīng)成功和失敗都有不同的回調(diào)函數(shù)。 為什么要異步編程 我們?cè)趯?xiě)前端代碼時(shí),經(jīng)常會(huì)對(duì)dom做事件處理操作,比如點(diǎn)擊、激活焦點(diǎn)、失去焦點(diǎn)等;再比如我們用ajax請(qǐng)求數(shù)據(jù),使用回調(diào)函數(shù)獲取返回值。這些都屬于異步編程。 也許你...

    ssshooter 評(píng)論0 收藏0
  • 深入理解ES6筆記(十一)Promise異步編程

    摘要:回調(diào)函數(shù)模式類似于事件模型,因?yàn)楫惒酱a也會(huì)在后面的一個(gè)時(shí)間點(diǎn)才執(zhí)行如果回調(diào)過(guò)多,會(huì)陷入回調(diào)地獄基礎(chǔ)可以當(dāng)做是一個(gè)占位符,表示異步操作的執(zhí)行結(jié)果。函數(shù)可以返回一個(gè),而不必訂閱一個(gè)事件或者向函數(shù)傳遞一個(gè)回調(diào)函數(shù)。 主要知識(shí)點(diǎn):Promise生命周期、Promise基本操作、Promise鏈、響應(yīng)多個(gè)Promise以及集成PromiseshowImg(https://segmentfaul...

    RayKr 評(píng)論0 收藏0
  • JS筆記

    摘要:從最開(kāi)始的到封裝后的都在試圖解決異步編程過(guò)程中的問(wèn)題。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。異步編程入門(mén)的全稱是前端經(jīng)典面試題從輸入到頁(yè)面加載發(fā)生了什么這是一篇開(kāi)發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門(mén)教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識(shí)之 HTTP 協(xié)議 詳細(xì)介紹 HTT...

    rottengeek 評(píng)論0 收藏0
  • ES6-7

    摘要:的翻譯文檔由的維護(hù)很多人說(shuō),阮老師已經(jīng)有一本關(guān)于的書(shū)了入門(mén),覺(jué)得看看這本書(shū)就足夠了。前端的異步解決方案之和異步編程模式在前端開(kāi)發(fā)過(guò)程中,顯得越來(lái)越重要。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(shū)(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書(shū)的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<