前端專案中常用es6知識總結 -- Promise逃脫回撥地獄
專案開發中一些常用的es6知識,主要是為以後分享小程式開發、node+koa專案開發以及vueSSR(vue服務端渲染)做個前置鋪墊。
專案開發常用es6介紹
-
1、塊級作用域 let const
-
2、箭頭函式及this指向
-
3、promise、
- 4、async await語法
-
4、模組化 module export和import
-
5、解構賦值、字串模板
-
……
Promise
Promise是什麼?不妨直接打印出來看吧! 在瀏覽器控制檯輸入console.dir( Promise )回車會有驚喜。
// 大家在瀏覽器控制檯輸入console.dir( Promise )看一下哈!!!
可以看到Promise是一個建構函式,它跟JS中的Date、Array等建構函式類似,使用new操作符例項化之後就可以通過傳參和呼叫方法的形式來完成某些特定的功能:
var date = new Date("2018-12-24 15:46:10");
date.getTime() //1545637570000
date.getFullYear() //2018
date.getDate() //24
同樣,我們也需要使用new操作符來例項化Promise建構函式,與其他建構函式不同的是Promise接收一個函式作為引數。該函式又接收兩個引數,分別是resolve和reject,resolve和reject也是函式(javascript內建的)且這兩個函式都有各自不同的作用。 resolve函式的作用是:將Promise物件的狀態從未完成變為成功(即從 pending 變為 resolved) reject函式的作用是:將Promise物件的狀態從未完成變為失敗(即從 pending 變為 rejected) 無論結果是成功還是失敗,都可以將需要傳遞的引數通過該函式傳遞出去,以下是程式碼示例:
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("我是資料")
}, 1000)
}) var failExample = new Promise(function(resolve, reject) {
setTimeout(function() {
reject(new Error('我錯了'))
}, 1000)
})
then方法
Promise 例項具有then方法,then方法的第一個引數是resolve(成功)的回撥,第二個引數(可選)是reject(失敗)的回撥。
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
if (false) {
resolve("我是資料")
} else {
reject(new Error('我錯了'))
}
}, 1000)
}) promise.then(function(data) {
console.log(data) // 我是資料 當if條件為真時觸發
}, function(err) {
console.log(err) // Error: 我錯了 當if條件為假時觸發
})
使用箭頭函式的話,程式碼會更簡潔:
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
false ? resolve("我是資料") : reject(new Error('我錯了'))
}, 1000)
}) promise.then(
(data) => console.log(data),
(err) => console.log(err)
)
catch方法
catch方法和then的第二個引數一樣,用來指定reject時的回撥,用法是這樣:
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
false ? resolve("我是資料") : reject(new Error('我錯了'))
}, 1000)
})
promise
.then(
(data) => console.log(data)
)
.catch(
(err) => console.log(err)
)
all方法
Promise.all方法用於將多個 Promise 例項,包裝成一個新的 Promise 例項。此方法提供了並行執行非同步操作的能力,並且在所有非同步操作執行完後才執行回撥。舉一個例子:開發中首頁可能會有多個介面,如果寫多個方法同時請求資料,很可能最終頁面展示的時候會一塊接一塊顯示出來就像是拼接完成的。通過Promise.all我們就可以將多個方法請求的資料同時展現出來:
var getData1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("1、介面1的資料")
}, 700)
}) var getData2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("2、介面2的資料")
}, 100)
}) var getData3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("3、介面3的資料")
}, 300)
}) Promise.all(
[getData1, getData2, getData3]
).then((data) => {
console.log(data) // ["1、介面1的資料", "2、介面2的資料", "3、介面3的資料"]
})
上述程式碼可以看出all接收一個數組作為引數,陣列成員分別是定義好的Promise例項,當所有的介面都成功時將按順序把返回的結果放到一個數組裡傳給then方法。
race方法
Promise.race方法同樣是將多個 Promise 例項,包裝成一個新的 Promise 例項。使用race方法時如果有一個率先成功,那麼就立即返回。由此可見all和race的區別是: all方法的效果實際上是 “誰跑的慢,以誰為準執行回撥”, race方法的效果實際上是 ”誰跑的快,以誰為準執行回撥”
var getData1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("1、介面1的資料")
}, 700)
}) var getData2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("2、介面2的資料")
}, 1000)
}) var getData3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("3、介面3的資料")
}, 300)
})
Promise
.race(
[getData1, getData2, getData3]
)
.then((data) => {
console.log(data)// 3、介面3的資料
})
Promise的出現主要是解決地獄回撥的問題,比如有一個功能需要請求很多個介面,且每一個介面的引數都需要另外一個的介面返回的資料作為依賴,這樣就需要我們一層巢狀一層,但是有了Promise 我們就無需巢狀,就可以使用then方法鏈式呼叫。