ES6學習筆記(六)【promise,Generator】
簡介
在ES6以前,我們處理非同步操作只能使用回撥函式
ES6中新增了幾種書寫非同步程式碼的解決方案,promise是最常用的一種
正文
Promise是一個建構函式,我們可以用new關鍵字生成一個promise例項來使用
let promise = new Promise((resolve, reject) => {
//做一些非同步操作
setTimeout(() => {
console.log('success')
resolve('promise is success')
}, 2000)
})
Promise建構函式接受一個函式作為引數,在這個函式內執行一些非同步操作
這個函式擁有兩個引數:resolve和reject,這兩個都是函式,js引擎會幫你傳入
在函式內部呼叫他們的時候分別代表對外宣告非同步操作已經成功(resolve)或失敗(reject)
為什麼會設計的這樣複雜?
setTimeout(() => {
return 1
}, 2000)
這是一個簡單的回撥方式處理非同步操作的結果,但是回撥函式被外層的定時器包裹
我們沒法簡單的拿到回撥函式的返回值,這也是回撥函式最大的缺陷
所以promise通過resolve和reject方法,對外傳遞一個可以輕易訪問到資訊
如果我們需要拿到並處理promise內部resolve的資訊,需要使用then方法:
let promise = new Promise((resolve, reject) => {
//做一些非同步操作
setTimeout(() => {
console.log('success')
resolve('promise is success')
}, 2000)
})
promise.then(x => console.log(x))
// promise is success
promise例項上的then方法是promise裡最常用的方法,它接受一個函式為引數,這個函式的第一個引數就是這個promise內部resolve出來的值,從而我們可以在這個函式內部獲取和使用這個值
另一個常用方法是catch,如果這個promise非同步操作出了問題
我們會在函式內部呼叫reject方法傳遞出去錯誤資訊,代表promise出錯了
這時候應該使用catch方法來處理錯誤資訊:
let promise = new Promise((resolve, reject) => {
//做一些非同步操作
setTimeout(() => {
console.log('error')
reject('promise is error')
}, 2000)
})
promise.then(x => console.log(x))
// 報錯 Uncaught (in promise) promise is success
promise.catch(x => console.log(x)
// 不報錯 輸出 promise is error
其實如果你給then方法傳入兩個函式,那麼第二個函式也是可以捕獲到這個錯誤的
catch方法只是then的一個別名,不過為了程式碼清晰易讀
我們最好都是用catch,而不是給then傳入兩個引數
現在我們有then方法處理執行成功的promise,用catch處理出錯的promise
顯然需要一種無論成功還是出錯都能處理的方法,就像try…catch中的finally
promise也提供了一個finally方法,用法與then,catch完全相同
無論promise成功還是失敗都會執行finally中的回撥函式
除了這四種promise例項上的方法以外,js還原生提供了Promise.resolve()和Promise.reject()方法
注意不是promise內部的resolve,reject方法,不要混淆
這兩個方法可以簡單的把一個非同步操作包裝成promise:
Promise.resolve('success')
// 等價於
new Promise((resolve, reject) => resolve('success'))
Promise.reject('error')
// 等價於
new Promise((resolve, reject) => reject('error'))
如果需要快速建立一個resolve或者reject狀態的promise,就用這兩個方法
promise建構函式也可以包裝多個promise例項,來讓一些非同步操作並行執行
let all = Promise.all([p1, p2, p3])
let race = Promise.race([p1, p2, p3])
Promise.all和Promise.race方法都接收一個可遍歷物件為引數,其中每一項都是一個promise例項
上面程式碼中 p1, p2, p3 都是一個promise例項,內部要執行一些非同步操作
在Promise.all生成的promise物件中,p1, p2, p3都完成(resolve)的時候,
它自身才算完成,自動呼叫內部的resolve方法
而Promise.race生成的promise的物件中.只要p1, p2, p3有一個完成
它就算完成,立刻呼叫resolve方法
但是還沒完成的也不會終止,最終三個promise也都會完成
思考
這部分內容希望你都可以手動敲一遍,獨立思考
嘗試用Promise封裝一個發GET請求的方法,接受一個url字串為引數
返回一個請求該URL的Promise,並且狀態碼為200時可以呼叫then方法獲取返回資料
狀態碼為其他時可以在catch中輸出報錯資訊
根據上面寫出的請求封裝函式生成三個請求不同url的Promise
並用Promise.race嘗試做一個延遲處理,一秒內沒有收到響應的請求就不再獲取資料
Generator
是ES6新增的一種函式,可以看做一個狀態機
通常我們通過Generator函式來實現一些非同步操作
正文
定義一個Generator函式需要在function關鍵字後加一個*號
function *f() {
yield 1
yield 2
}
let a = f()
a.next() // {value: 1, done: false}
a.next() // {value: 2, done: false}
a.next() // {value: undefined, done: true}
a.next() // {value: undefined, done: true}
顯然我們定義個一個叫做f的Generator函式,那麼f可以看做是一個狀態機
f的內部我們用 yield
關鍵字定義了兩個 狀態
然後我們通過f()執行這個函式,與普通函式不同的是,Generator函式執行後,
得到的結果並不是函式的返回值,而是而是一個代表其內部狀態的Iterator
Iterator我們之前已經介紹過了,是一個通用的遍歷器介面,我們可以呼叫它上面的next方法得到其內部的值
yield
命令用在Generator函式體中,與return類似,停止執行函式並把它後面的表示式的值返回
yield
把Generator函式體劃分成一塊一塊來執行,每次呼叫next方法,都會使函式繼續向下執行,直到遇見下一個 yield
並把值放在value裡返回
如果後續再沒有其他 yield
或return 就把done欄位置為true,代表全部的狀態都已執行完畢
正常情況下我們不會手動去一次次呼叫next檢視結果,而是使用 for...of
迴圈:
function *f() {
yield 1
yield 2
}
for(let x of f()){
console.log(x)
}
// 1 2
關於Generator的細節知識點很多,比如next還可以傳入引數影響Generator函式內部狀態等等
不過時至今日(17年6月),Generator在開發中的應用已經很少了,這裡不再為新手介紹其他知識
主流的非同步方案已經逐漸成型,目前我們使用Promise和Async來解決非同步問題
思考
這部分內容希望你都可以手動敲一遍,獨立思考
嘗試寫出一個表示斐波那契數列的Generator函式
函式接收一個引數,代表生成的斐波那契數列的長度
function* fib(length){
// 做一些操作,然後使用yield返回每一步的結果
}
for(let x of fib(7)){
console.log(x)
}
// 輸出 [1, 1, 2, 3, 5, 8, 13]
相關文章
- ES6語法學習筆記之promise筆記Promise
- Promise學習筆記Promise筆記
- Promise 學習筆記Promise筆記
- Promise 物件學習筆記Promise物件筆記
- ES6 學習筆記筆記
- ES6 學習筆記筆記
- es6學習筆記筆記
- Promise學習筆記(知識點 + 手寫Promise)Promise筆記
- Javascript 學習 筆記六JavaScript筆記
- 學習筆記:javascript中的Generator函式筆記JavaScript函式
- ES6 學習筆記四筆記
- ES6 學習筆記一筆記
- ES6 學習筆記二筆記
- ES6 學習筆記三筆記
- ES6的學習筆記筆記
- ES6中的Promise和Generator詳解Promise
- HexMap學習筆記(六)——河流筆記
- android學習筆記六Android筆記
- Spss 學習筆記(六)SPSS筆記
- ES6學習筆記--es6簡介筆記
- ES6學習筆記(七)【class】筆記
- ES6學習筆記(八)【class】筆記
- ES6學習筆記(九)【class】筆記
- ES6學習筆記之Function筆記Function
- 前端學習筆記之ES6~~~前端筆記
- ES6 中 Promise物件使用學習Promise物件
- vue學習筆記(六) ----- vue元件Vue筆記元件
- 大資料學習筆記(六)大資料筆記
- ES6學習筆記3---Symbol筆記Symbol
- 記錄學習PromisePromise
- Async & generator & PromisePromise
- JavaScript學習筆記(一) promise和async/waitJavaScript筆記PromiseAI
- python學習筆記(六)——函式Python筆記函式
- Vue學習筆記(六) 長樂未央Vue筆記
- 學習筆記|AS入門(六) 碎片Fragment筆記Fragment
- ES6 - Promise, Generator, async(非同步操作)使用比較Promise非同步
- ES6學習筆記(一)【變數,字串】筆記變數字串
- ES6學習筆記(三)【函式,物件】筆記函式物件