javascript Promise
阿新 • • 發佈:2022-02-21
回撥函式
對比-普通函式和非同步函式返回值
- 普通函式的直接返回想要的資料,可以非同步函式不行,於是便有了回撥函式.
進化-回撥函式
例子1
- 以前是我希望呼叫你這個函式,然後能夠給我返回一些資料,在我這裡進行處理,但是我拿不到資料
- 現在呢,我呼叫你這個函式,感覺我把怎麼處理這些資料的流程都告訴你了,然後在你那裡處理資料吧.
- 或者這樣理解,以前,資料的處理流程和執行流程都在我這裡
- 現在,我把資料的處理流程告訴你,然後在你那裡進行執行
例子2
-
如果requestData()是個普通函式,也就是裡面沒有非同步程式碼,那麼我在20行呼叫這個函式,就是希望這個函式能夠返回某個結果來讓我進行處理.
-
但是因為這個requestData()是個非同步請求函式,所以我直接去呼叫這個函式,他並不是立刻馬上就返回一些結果給我,然後進行後續的資料處理.
-
所以我傳遞兩個回撥函式給他,然後讓他執行.
-
存在的缺點:
- 就是不熟悉這個函式的,需要查閱api文件,才能夠使用這個函式,很麻煩
- 互動不是很友好
進化-Promise
- 非同步函式,返回資料時,返回的資料都是空的.
- 於是出現了回撥函式,不要非同步函式返回資料了.
- 現在,出現了一個"承諾",非同步函式不返回具體的資料了,而是返回一個"承諾"
- 然後我根據這個"承諾"的狀態,來決定做哪種處理
function requestData() { return new Promise((resolve, reject) => { resolve('這是--成功--返回的資料'); // reject('這是--失敗--返回的資料'); }); } const promise = requestData(); promise.then( (result) => { console.log(result); }, (reason) => { console.log(reason); } );
成功的回撥
失敗的回撥
簡寫形式-Promise
Promise的承諾移交
通過resolve移交_看後面
- 沒執行,時因為這個newPromise的狀態時Pending狀態.
-
執行了,是因為這個新承諾的狀態變成Resolved
-
簡單總結:
- 執行哪個函式取決於新的承諾
const newPromise = new Promise((resolve, reject) => { resolve('承諾被移交給我啦'); }); new Promise((resolve, reject) => { resolve(newPromise); // reject('這是--失敗--返回的資料'); }).then( (result) => { console.log(result); }, (reason) => { console.log(reason); } );
通過reject移交_註定失敗
- 通過reject移交的承諾,無論後邊的承諾怎麼變化,最後的結果是都時是失敗的承諾
const newPromise = new Promise((resolve, reject) => {
resolve('承諾被移交給我啦');
// reject('承諾被移交給我啦,但是沒有兌現');
});
new Promise((resolve, reject) => {
// resolve(newPromise);
reject(newPromise);
}).then(
(result) => {
console.log('result:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
console.log(result);
},
(reason) => {
console.log('reason:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
console.log(reason);
}
);
通過then方法移交_看後面
- 前面的都是傳入一個Promsie來進行承諾移交
- 其實也是可以傳入一個包含then方法的物件,來進行狀態移交
- 那麼這個"承諾"的狀態則取決於這個then方法裡面的成功或失敗
const obj = {
then: function (resolve, reject) {
// resolve('這個then方法中的成功承諾');
reject('這個then方法中的失敗承諾');
},
};
new Promise((resolve, reject) => {
resolve(obj);
// reject(obj);
}).then(
(result) => {
console.log('result:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
console.log(result);
},
(reason) => {
console.log('reason:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
console.log(reason);
}
);
輸出效果
Promise中的立即執行和延後執行
立即執行
- 傳入Promise()括號的函式都是立即執行的
延後執行
- Promise().then()後面的then裡面傳入的函式不是立即執行,要等待"承諾"的狀態
Promise的多次呼叫
- 同一個Promise物件,呼叫多次then方法,則每個then方法都會執行一次
Promise中then方法的鏈式呼叫↓↓↓↓↓↓↓↓
then方法的返回值
- 如果你返回的是一個普通的物件,比如字串,數字,物件等等,系統會自動將其轉換成一個Promise,然後這個普通的物件作為resolve()的引數
- 當然你也可以直接返回一個Promise物件,上面可以認為是一種語法糖形式
- 其次就是要區分,Promise的多次呼叫和鏈式呼叫
- 多次呼叫:同一個Promise物件,多次呼叫then方法
- 鏈式呼叫:原來的Promise物件,只調用一次then方法,後面的then方法,是由前面的then方法產生的新的Promise物件來呼叫的.
Promise中的的catch方法
- 可以捕獲前面的then方法中新生成的promise的"失敗承諾"
- 也可以捕獲原始的Promise物件的"失敗承諾"
- 也就是說,建立一個Promise物件之後,然後採用鏈式呼叫then()方法,不論呼叫多少次,這個catch方法都會從第一個承諾開始捕獲"失敗的承諾",如果其中有一個"失敗承諾",就是會捕獲到
類方法Promise.resolve()
傳入一個普通物件
- 可以將一個普通物件轉換成promise
- 和使用
new Promise((resolve,reject)=>{ resolve([普通物件])})
的效果是一樣的
傳入一個Promise物件
成功的Promise
失敗的Promise
類方法Promise.reject()
- 即使傳入一個成功的承諾,也是跳到catch裡面執行,
- 因此,可以把Promise.reject()裡面的東西當作字串來進行處理.
類方法Promise.all()
- Promise.all()要等號前面的三個promise物件都變成fullfilled,再拿到結果
- 在數組裡面放上三個promise物件,當然,也可以放上普通物件,這個時候,他會將這個普通物件轉換成Promise物件,然後和前面的內容引數,拼接成一個數組
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1111');
}, 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2222');
}, 1000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('3333');
}, 1000);
});
Promise.all([p1, p2, p3, '4444']).then((res) => {
console.log('res: ' + res);
});
- 只要其中有一個是reject,那麼就是執行catch
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1111');
}, 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('2222');
reject('2222');
}, 1000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('3333');
}, 1000);
});
Promise.all([p1, p2, p3, '4444'])
.then((res) => {
console.log('res: ' + res);
console.log(res);
})
.catch((reason) => {
console.log('resason: ' + reason);
});
類方法Promise.allSettled()
- 這個方法要和Promise.all()區分開來
- Promise.all()是隻要遇到一個失敗的承諾,就會返回
- Promise.allSettled()不管你其中有沒有失敗的承諾,等你全部的承諾都是執行完畢,再返回
- 所以Promise.allSettled()中,可以看到所有promise的狀態
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1111');
}, 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('2222');
reject('2222');
}, 1000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('3333');
}, 1000);
});
Promise.allSettled([p1, p2, p3, '4444'])
.then((res) => {
console.log(res);
})
.catch((reason) => {
console.log(reason);
});
類方法Promise.race()
- race這個詞有比賽,賽跑的意思
- 所以,故名顧名思義,前面三個promise物件,誰先完成,就結束返回
類方法Promise.any()
- 前面三個Promise物件中,至少有一個是resolve的,就會fullfilled
- 如果前面三個Promise物件,全部都是reject,最終才會rejected