您好,登錄后才能下訂單哦!
如何在ES6中使用Promise對象?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
一、 Promise是什么
Promise是異步編程的一種解決方案,它是一個容器,里面保存著某個未來才會結束的事件的結果。它有三種狀態,只有異步操作的結果才能決定當前的狀態,不受外界因素的影響。而一旦狀態改變,就不會再變,也就是狀態凝固了(resolved),任何時候都可以得到這個結果。
Promise的缺點:
1. 無法取消Promise,一旦新建它就會立即執行,無法中途取消。
2. 如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。
3. 當處于pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
二、Promise的用法
/** * 創建Promise實例 * @type {Promise} * @param resolve 在異步操作成功時調用 * @param reject 在異步操作失敗時調用 */ const promise = new Promise(function(resolve, reject) { // ... some code if (/* 異步操作成功 */){ resolve(value); } else { reject(error); } }); //調用Promise promise.then(function(value) { // success }, function(error) { // failure });
Promise 新建后就會立即執行。
let promise = new Promise(function(resolve, reject) { console.log('Promise'); resolve(); }); promise.then(function() { console.log('resolved.'); }); console.log('Hi!'); // Promise (Promise 新建后立即執行,所以首先輸出的是Promise) // Hi! // resolved (then方法指定的回調函數,將在當前腳本所有同步任務執行完才會執行,所以resolved最后輸出)
如果調用resolve函數和reject函數時帶有參數,那么它們的參數會被傳遞給回調函數。reject函數的參數通常是Error對象的實例,表示拋出的錯誤;resolve函數的參數除了正常的值以外,還可能是另一個 Promise 實例。
const p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('fail')), 3000) }) const p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000) }) p2 .then(result => console.log(result)) .catch(error => console.log(error)) // Error: fail
上面代碼中,p1是一個 Promise,3 秒之后變為rejected。p2的狀態在 1 秒之后改變,resolve方法返回的是p1。由于p2返回的是另一個 Promise,導致p2自己的狀態無效了,由p1的狀態決定p2的狀態。所以,后面的then語句都變成針對后者(p1)。又過了 2 秒,p1變為rejected,導致觸發catch方法指定的回調函數。
三、Promise原型上的方法
Promise.prototype.then()
then方法的第一個參數是resolved狀態的回調函數,第二個參數(可選)是rejected狀態的回調函數。
then方法返回的是一個新的Promise實例,但不是原來那個Promise實例。因此可以采用鏈式寫法,即then方法后面再調用另一個then方法。
getJSON("/post/1.json").then( post => getJSON(post.commentURL) ).then( comments => console.log("resolved: ", comments), err => console.log("rejected: ", err) );
Promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的別名,用于指定發生錯誤時的回調函數。
Promise 對象的錯誤具有“冒泡”性質,會一直向后傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch語句捕獲。
getJSON('/post/1.json').then(function(post) { return getJSON(post.commentURL); }).then(function(comments) { // some code }).catch(function(error) { // 處理前面三個Promise產生的錯誤 }); //上面代碼中,一共有三個 Promise 對象:一個由getJSON產生,兩個由then產生。它們之中任何一個拋出的錯誤,都會被最后一個catch捕獲。
Promise.prototype.finally()
finally方法用于指定不管 Promise 對象最后狀態如何,都會執行的操作。該方法是 ES2018 引入標準的。
finally方法的回調函數不接受任何參數,這意味著沒有辦法知道,前面的 Promise 狀態到底是fulfilled還是rejected。這表明,finally方法里面的操作,應該是與狀態無關的,不依賴于 Promise 的執行結果。
四、Promise的方法
Promise.all()
Promise.all方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。
const p = Promise.all([p1, p2, p3]);
只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成一個數組,傳遞給p的回調函數。
只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。
如果p1、p2、p3有自己的catch方法,則不會觸發p的catch方法,如果沒有,才會調用Promise.all()的catch方法。
const p1 = new Promise((resolve, reject) => { resolve('hello'); }) .then(result => result) .catch(e => e); const p2 = new Promise((resolve, reject) => { throw new Error('報錯了'); }) .then(result => result) .catch(e => e); Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); // ["hello", Error: 報錯了] ------------------------------------------------------------------- const p1 = new Promise((resolve, reject) => { resolve('hello'); }) .then(result => result); const p2 = new Promise((resolve, reject) => { throw new Error('報錯了'); }) .then(result => result); Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); // Error: 報錯了
Promise.race()
Promise.race方法同樣是將多個 Promise 實例,包裝成一個新的 Promise 實例。
race內部的一個實例率先改變狀態,Promise.race()的狀態就跟著改變。那個率先改變的Promise實例的返回值,就傳遞給Promise.race()的回調函數。
Promise.resolve()
有時需要將現有對象轉為 Promise 對象,Promise.resolve方法就起到這個作用。
Promise.resolve方法的參數分成四種情況。
參數是一個 Promise 實例:如果參數是 Promise 實例,那么Promise.resolve將不做任何修改、原封不動地返回這個實例。
參數是一個thenable對象:thenable對象指的是具有then方法的對象,Promise.resolve方法會將這個對象轉為 Promise 對象,然后就立即執行thenable對象的then方法。
參數不是具有then方法的對象,或根本就不是對象:如果參數是一個原始值,或者是一個不具有then方法的對象,則Promise.resolve方法返回一個新的 Promise 對象,狀態為resolved。
不帶有任何參數:Promise.resolve方法允許調用時不帶參數,直接返回一個resolved狀態的 Promise 對象。
需要注意的是,立即resolve的 Promise 對象,是在本輪“事件循環”(event loop)的結束時,而不是在下一輪“事件循環”的開始時。
setTimeout(function () { console.log('three'); }, 0); Promise.resolve().then(function () { console.log('two'); }); console.log('one'); // one // two // three
Promise.reject()
Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態為rejected。
注意,Promise.reject()方法的參數,會原封不動地作為reject的理由,變成后續方法的參數。這一點與Promise.resolve方法不一致。
const thenable = { then(resolve, reject) { reject('出錯了'); } }; Promise.reject(thenable) .catch(e => { console.log(e === thenable) }) // true
五、Promise的應用
包裝http請求
在使用vue的過程中,我們用Promise對Axios進行了包裝。
newAxios.post = function (url, params) { params = qs.stringify(params); return new Promise((resolve, reject) => { Axios.post(url, params) .then(res => { if (res.headers.warning === "redirect") { window.location.href = "/" } else { resolve(res); } }) .catch(err => { reject(err); }) }) };
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。