Promise是ES6中用來結局回調地獄的問題的但是並不能幫我們減少代碼量
-
-
在Promise上有兩個函數分別是resolve(成功之后的回調函數)和reject(失敗之后的回調函數)
-
在Promise構造函數的prototype屬性上,有一個.then()方法,也就是只要是Promise構造函數創建的實例,都可以訪問到.then()方法
-
如果Promise表示一個異步操作,每當我們new一個Promise的實例,這個實例就表示一個具體的異步操作
-
既然Promise創建的實例是一個異步操作那么這個異步操作的結果只能有兩種狀態
-
狀態一:異步執行成功 需要在內部調用,成功的回調函數resolve 把結果返回給調用者
-
狀態二:異步執行失敗了 需要在內部調用,成功的回調函數reject把結果返回給調用者
-
由於Promise的實例是一個異步操作,所以拿到操作結果后,無法使用return把操作結果返回給調用者,這個時候只能使用回調函數的形式,來把成功或者失敗的結果返回給調用者
-
-
我們可以在new出來的Promise實例上,調用.then()方法【預先】為這個Promise一部操作,指定成功(resolve)和失敗(reject)回調函數
實現原理:(以讀取文件為例)
1 //這是一個具體的異步操作,其中使用function 指定一個具體的異步操作 2 var promise = new Promise(function () { 3 //這個function 內部寫的就是具體的異步操作 4 }) 5 //每當new一個Promise實例的時候,就會立即執行這個異步操作中的代碼 6 //如果不想立即執行需要放在一個函數中調用才執行 7 function getFile(fpath) { 8 var promise = new Promise(function (resolve,reject) { 9 fs.readFile(fpath,'utf-8',function (err,data) { 10 if(err) { 11 //console.log(err.message) 12 reject(err) 13 return false 14 } 15 //console.log(data); 16 resolve(data) 17 }) 18 }); 19 return promise 20 } 21 var p = getFile(path).then(function (data) { 22 console.log(data) 23 },function (err) { 24 console.log(err.message) 25 })
回調地獄的寫法(了解即可)
getFile(path.join(__dirname,'./file/1.txt')).then((data)=>{ console.log(data); getFile(path.join(__dirname,'./file/2.txt')).then((data)=>{ console.log(data); getFile(path.join(__dirname,'./file/3.txt')).then((data)=>{ console.log(data); }) }) })
注意:回調嵌套只會降低效率,並且如果需要讀取的文件太多,不好排錯,在沒有將代碼執行完畢之前你永遠不知道這段代碼是在干什么
正確的寫法:
//在上一個.then中返回一個新的promise實例,可以繼續用下一個.then來處理 getFile('路徑1').then(function (data) { console.log(1,data); return getFile('路徑2') }).then(function (data) { console.log(2,data); return getFile('路徑3') }).then(function (data) { console.log(3,data); })
如果執行失敗了不想影響后續的promise的正常執行此時我們需要單獨為每一個promise通過.then指定一下失敗的回調
getFile(path).then(function (data) { console.log(data) return getFile(path) },function (err) { console.log(err.message) return getFile(path) }).then(function (data) { console.log(data) return getFile(path) },function (err) { console.log(err.message) return getFile(path) })
不管是正確的回調函數還是失敗的回調函數都需要將下一個回調函數所需要的對象return出去
如果前面的失敗了,則后面的就沒有繼續執行下去的意義,此時我們想實現一旦報錯則立即終止所有的promise的執行;
//在promise的最后使用catch .catch(function (err) { //catch如果前面有任何的promise執行失敗,則立即終止所有promise的執行並馬上進入catch去處理promise中拋出異常 console.log('這是自己的處理方式:'+err.message) })