1. 程式人生 > >Promise 之初探

Promise 之初探

陳舊的知識應該更新一下了,先嚐試一下 Promise ,主要參考 [https://www.cnblogs.com/whybxy/p/7645578.html](https://www.cnblogs.com/whybxy/p/7645578.html) # 定義一個函式 直接上乾貨,定義一個函式: ```js const myPost = (url, data) => { // 接收url 和data,向後端提交 console.log('url:', url) console.log('data:', data) const p = new Promise((resolve,reject)=>{ // resolve,reject是形式引數,可以是任意寫法,如(res, rej),預設第一個引數實現的是resolve功能;第二個引數實現的是reject功能。 console.log("myPost:") data.push('處理完畢') resolve(data) // 返回引數 // resolve()不同於return, resolve()執行完成後後面的程式碼還會執行。 reject('失敗了') }) return p } ``` 這個函式,假裝要向後端提交申請,然後返回後端給的資料。 const p = new Promise() 定義一個例項,簡單理解,resolve 是成功的回撥函式,reject 是失敗的回撥函式。 > 注意:這裡只是簡單理解,實際上並不完全是這樣。 # 單次呼叫 ~~~js myPost('url1', [1,2,3]).then((data) => { console.log("單次呼叫的結果:") console.log(data) },(msg) => { console.log('myPost的else'+msg) }) ~~~ 傳入url和需要提交的資料,然後在then裡面等待結果。then裡面第一個方法是成功的回撥,第二個方法是失敗的回撥。 我們看一下執行結果: ![](https://img2020.cnblogs.com/blog/17148/202012/17148-20201221141843143-1893642706.jpg) # 依次呼叫 ~~~js myPost('urla', [1,2,3]).then((data) => { console.log("第一個呼叫完成:") console.log(data) return myPost('urlb', data) // 發起第二次請求 }).then((data) => { console.log("第二個呼叫完成:") console.log(data) return myPost('urlc', data) // 發起第三次請求 }).then((data) => { console.log("第三個呼叫完成:") console.log(data) return myPost('urld', data) // 發起第四次請求 }).then((data) => { console.log("第四個呼叫完成:") console.log(data) }) ~~~ 有的時候需要多次向後端提交申請,而且需要前一次申請得到的資料,才能發起下一次申請。 那麼可以用這種依次申請的方式。 先發起第一個申請,然後得到資料,然後依據資料發起第二次申請,同理可以依次發起n次申請。 因為是得到結果才能發起下次申請,所以提交順序和返回順序皆可以控制。 看一下執行結果: ![](https://img2020.cnblogs.com/blog/17148/202012/17148-20201221142540239-1685402461.jpg) > 這裡有個小問題,第一次訪問的結果裡面 console.log(data) 出來的是四個陣列元素,這個是期待的,但是開啟看裡面卻有7個。這就奇怪了。 # 批量一起呼叫 ~~~js Promise.all([ myPost('urla', [1,2,3]), myPost('urlb', [1,2,3]), myPost('urlc', [1,2,3]) ]).then((data) => { console.log("一起呼叫,一起返回:") console.log(data) console.log(data[1]) },(msg) => { console.log(msg) }) ~~~ 有的時候,向後端發出的申請,可以一起提交,並不需要上次返回的結果,那麼可以這麼寫,這樣是不是比then.then.then的好看多了。 那麼返回的資料是啥樣子的呢?是陣列,順序和上面提交的順序是一致的。 我們來看看結果: ![](https://img2020.cnblogs.com/blog/17148/202012/17148-20201221143106356-1942868629.jpg) 這裡也有個意外,本來以為一起呼叫的結果,會出現在依次訪問的第四次訪問結果的後面。 但是實際情況卻發生了“亂入”。 一起訪問的結果,插入了依次訪問的“內部”。 這裡並沒有使用settimeout來模擬後端訪問,本來以為都是順序執行,但是實際並不是,估計是promise內部的一些原理導致的,先不去研究了,暫時先這樣。第一步先會用,知道返回的順序的特點。 > 這裡的返回結果,並沒有出現數組元素數量莫名增加的情況。問題出在哪裡,在繼續研究。 # 疑問: * 你可能會奇怪,這個根本就沒有任何訪問後端的程式碼嘛,忽悠人是不是? 其實並不是,現在流行的axios就是依據promise來實現的,也就是說axios本身就是一個promise例項,相當於函式裡面的p。 我們把promise的使用方式理解了之後,使用axios實現向後端的訪問,就輕鬆多了。 另外這裡是熟悉promise的用法,並不是熟悉axios的用法。 * 另一個問題是,為啥要自己寫個函式,直接用axios不香嗎? 這個和個人習慣有關係。我總是習慣自己再多加一層,這樣函式名稱、引數、返回方式就都可以歸我個人來控制了, 這樣便於應對版本升級,更換第三方類庫,增加自己想要的功能。 比如我想加入前端儲存的功能,提交的資料在前端 localStorage 裡面儲存一份的話,就可以直接在自己定義的函式裡面實現,而不用在頁面程式碼裡面增加呼叫的