ES6——举个例子理解Promise的原理和使用
1. Promise 之前
1.1 回調(diào)函數(shù)
回調(diào)函數(shù):把函數(shù)A當(dāng)作參數(shù)傳遞給另一個函數(shù)B調(diào)用,那么A就是回調(diào)函數(shù)。
一些例子
具名回調(diào)
匿名回調(diào)
function 你有幾只狗(fn){fn('一只狗') } 你有幾只狗(function(數(shù)量){ console.log(數(shù)量) }) // 一只狗 復(fù)制代碼常見的例子
jQuery中使用回調(diào)函數(shù),這里用的是匿名回調(diào)的方式
1.2 回調(diào)地獄(回調(diào)缺點(diǎn)1)
回調(diào)地獄:指的是回調(diào)嵌套過多的情況,導(dǎo)致代碼很難被看懂。
let info = [] function 你有幾只狗(fn){fn('一只狗') } function 你有幾只貓(fn){fn('一只貓') } function 知道了(數(shù)量,callback){info.push(數(shù)量)console.log(info)if(callback){callback()} } // 開始調(diào)用 如果比這再多幾層,就不容易看懂了 你有幾只狗(function(狗數(shù)){console.log(狗數(shù))知道了(狗數(shù), function(){你有幾只貓(function(貓數(shù)){console.log(貓數(shù))知道了(貓數(shù))})}) }) 復(fù)制代碼1.3 不使用Promise,如何解決
利用具名函數(shù)代替匿名函數(shù)
let info = [] function 你有幾只狗(fn){fn('一只狗') } function 你有幾只貓(fn){fn('一只貓') } function 知道了(數(shù)量,callback){info.push(數(shù)量)console.log(info)if(callback){callback()} } function 告訴你貓的個數(shù)(貓數(shù)){console.log(貓數(shù))知道了(貓數(shù)) } function 繼續(xù)數(shù)(){你有幾只貓(告訴你貓的個數(shù)) } function 告訴你狗的個數(shù)(狗數(shù)){console.log(狗數(shù))知道了(狗數(shù), 繼續(xù)數(shù)) } 你有幾只狗(告訴你狗的個數(shù)) // 好像也沒好到哪去。。。 復(fù)制代碼1.4 回調(diào)方式各不相同,需要單獨(dú)記憶(回調(diào)缺點(diǎn)2)
readFile('C:\\1.txt',function (error, data) { // node.js 讀取文件方法中的回調(diào)if(error) {console.log('成功')console.log(data.toString())} else {console.log('讀取文件失敗')}})$.ajax({ // jQuery中ajax方法中的回調(diào)url:'/2.txt'success: function(response) {console.log('成功')},error: function(){console.log('失敗')} }) 復(fù)制代碼2. Promise 的目的
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對象。
3. Promise 的原理
3.1 實(shí)現(xiàn)原理
ES6 規(guī)定,Promise對象是一個構(gòu)造函數(shù),用來生成Promise實(shí)例。通過在函數(shù)內(nèi)部return 一個 Promise對象的實(shí)例,這樣就可以使用Promise的屬性和方法進(jìn)行下一步操作了。
function 函數(shù)名(){return new Promise(function(resolve, reject) {// ... some codeif (/* 異步操作成功 */){resolve(value); // 異步操作成功時調(diào)用,把結(jié)果作為參數(shù)傳遞出去} else {reject(error); // 異步失敗時調(diào)用,把錯誤作為參數(shù)傳遞出去}}) } 復(fù)制代碼3.2 調(diào)用邏輯
S1和E1兩個都沒有報錯,執(zhí)行S2(resolve執(zhí)行,系統(tǒng)認(rèn)為搞定了,沒報錯)S1和E1任何一個有報錯,執(zhí)行E2(reject執(zhí)行,系統(tǒng)認(rèn)為沒搞定,報錯了)
4. Promise 的使用
4.1 Promise 的屬性與方法
屬性
Promise.prototype
表示 Promise 構(gòu)造器的原型
方法
Promise.prototype.then()
返回一個 Promise 。它最多需要有兩個參數(shù):Promise 的成功和失敗情況的回調(diào)函數(shù)。
Promise.prototype.catch()
返回一個Promise,并且處理拒絕的情況。等價于Promise.prototype.then(undefined, onRejected)
Promise.prototype.finally()
finally() 方法返回一個Promise,在執(zhí)行then()和catch()后,都會執(zhí)行finally指定的回調(diào)函數(shù)。避免同樣的語句需要在then()和catch()中各寫一次的情況。
Promise.all(iterable)
返回一個 Promise 實(shí)例,iterable參數(shù)內(nèi)所有的 promise 都resolved后,才回調(diào)完成resolve。
Promise.race(iterable)
返回一個 promise ,并伴隨著 promise對象解決的返回值或拒絕的錯誤原因, 只要 iterable 中有一個 promise 對象"解決(resolve)"或"拒絕(reject)"。
Promise.resolve()
返回一個以給定值解析后的Promise對象。但如果這個值是個thenable(即帶有then方法),返回的promise會“跟隨”這個thenable的對象,采用它的最終狀態(tài)(指resolved/rejected/pending/settled);如果傳入的value本身就是promise對象,則該對象作為Promise.resolve方法的返回值返回;否則以該值為成功狀態(tài)返回promise對象。
Promise.reject()
返回一個帶有拒絕原因reason參數(shù)的Promise對象。
4.2 將回調(diào)地獄中的例子,改寫為Promise的形式
可以看到使用 Promise后,邏輯變得非常直觀
寫得更完整一些 Promise套Promise時,也就是Promise鏈的時候——注意信息的傳遞
一個失敗的例子,當(dāng)我們使用Promise鏈的時候,如果每一步都需要上一步的數(shù)據(jù)時,就需要傳參,成功通過resolve傳參,失敗通過reject傳參,如果忘記傳參,就得不到想要的結(jié)果。
resolve把成功的數(shù)據(jù)返回給下一個回調(diào)
reject把失敗的數(shù)據(jù)返回給下一個回調(diào)。
給這里的resolve傳一個參 改成失敗的例子
先不給reject傳參,如果失敗的話,下一個回調(diào)拿不到數(shù)據(jù) 給 reject傳參 我們可以看到,即使是走的失敗回調(diào),下一個成功回調(diào)還是執(zhí)行了,由于 不知道() 默認(rèn)返回undefined, 相當(dāng)于失敗已經(jīng)處理了,在成功和失敗都被處理的情況下,下一個回調(diào)會執(zhí)行的。
改成符合預(yù)期的,即失敗不調(diào)用。
失敗不調(diào)用的簡寫形式 上述情況執(zhí)行后 .then(除了狗呢)里面的成功回調(diào)沒有執(zhí)行,我們增加一個失敗回調(diào)看看 同樣也可以返回 resolve,讓后面成功回調(diào)可以執(zhí)行
4.3 應(yīng)用
加載圖片 將圖片的加載寫成一個Promise,一旦加載完成,Promise的狀態(tài)就發(fā)生變化。
const preloadImage = function (path) {return new Promise(function (resolve, reject) {const image = new Image();image.onload = resolve;image.onerror = reject;image.src = path;}); }; 復(fù)制代碼Generator 函數(shù)與 Promise 的結(jié)合(詳情見參考鏈接,阮一峰的教程)
5. 干掉Promise中的回調(diào)
5.1 await
成功的情況
失敗的情況 利用 try catch await 配合 try catch使用,比較完整6. 總結(jié)
能利用Promise對象,把普通函數(shù)改成返回Promise的形式,解決回調(diào)地獄的問題。
明白Promise的成功失敗調(diào)用邏輯,可以靈活的進(jìn)行調(diào)整。
理解核心知識,先用起來,慢慢整合吸收知識。
7. 參考鏈接
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
- http://es6.ruanyifeng.com/#docs/promise
- https://www.w3cplus.com/javascript/Sexy-Javascript-understand-the-callback-function-with-the-use-of-Javascript-in.html
- https://juejin.im/entry/57fa6a4e67f3560058752542
轉(zhuǎn)載于:https://juejin.im/post/5b0e07d85188253bdb1b3d61
總結(jié)
以上是生活随笔為你收集整理的ES6——举个例子理解Promise的原理和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux20180528
- 下一篇: Linux终端程序用c语言实现改变输出的