您好,登錄后才能下訂單哦!
今天小編給大家分享一下es6 promise有哪些狀態的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
有3種狀態:1、pending,表示正在進行中,該狀態會進行初始化;2、fulfilled,表示已成功;3、rejected,表示已失敗,會觸發后續的catch回調函數。promise的狀態發生改后就會凝固,不會再變,會一直保持這個結果。
本教程操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。
Promise 是異步編程的一種解決方案,比傳統的解決方案(回調函數和事件)更合理和更強大。
所謂Promise,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。
從語法上說,Promise 是一個構造函數,從它可以獲取異步操作的消息。
Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。有了Promise對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。
Promise對象提供統一的接口,使得控制異步操作更加容易。
我們知道,es5是單線程語言,語句執行順序由上往下,而項目前端對接后端時,需要用到ajax,而ajax是異步的,可能導致數據的交互產生延遲,不利于編程。而promise函數可以很好的解決這個問題。
Promise
構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve
和reject
。而這兩個參數是兩個函數,由 JavaScript 引擎提供。
Promise對象代表一個異步操作,有三種狀態: pending(進行中)、fulfilled(已成功)和rejected(已失敗)。
初始化,狀態:pending
當調用resolve(成功),狀態:pengding=>fulfilled
當調用reject(失敗),狀態:pending=>rejected
狀態發生改變之后就凝固了,不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。
狀態變化:
1、pending -> resolved
2、pending -> rejected
狀態的表現
pending狀態不會觸發then和catch
resolved狀態會觸發后續的then回調函數
rejected狀態會觸發后續的catch回調函數
then和catch改變狀態
then正常情況下會返回resolved,報錯則返回rejected
catch正常情況下會返回resolved,報錯則返回rejected
const promise = new Promise(function(resolve,reject){ //...some code if(/*異步操作成功*/){ resolve(value); // 狀態由pending變為fulfilled }else{ reject(error); // 狀態由pending變為rejected } })
例如:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>測試</title> </head> <body> <script> let promise = new Promise(function (resolve, reject) { if (3 < 5) { resolve("是正確的"); } else { reject("是錯誤的"); } }) console.log(promise); </script> </body> </html>
結果:
定義在Promise.prototype
中的方法,通過Promise實例可以直接調用。
當狀態由pending變為fulfilled的時候執行該回調函數,
參數:
最多需要有兩個參數,Promise 的成功和失敗情況的回調函數。
返回值:
返回一個新的Promise實例對象,因此可以使用鏈式調用。
當一個 Promise 完成(fulfilled)或者失敗(rejected)時,返回函數將被異步調用(由當前的線程循環來調度完成)。具體的返回值依據以下規則返回。如果 then 中的回調函數:
返回了一個值,那么 then 返回的 Promise 將會成為接受狀態,并且將返回的值作為接受狀態的回調函數的參數值。
沒有返回任何值,那么 then 返回的 Promise 將會成為接受狀態,并且該接受狀態的回調函數的參數值為 undefined。
throw拋出一個錯誤,那么 then 返回的 Promise 將會成為拒絕狀態,并且將拋出的錯誤作為拒絕狀態的回調函數的參數值。
返回一個已經是接受狀態的 Promise,那么 then 返回的 Promise 也會成為接受狀態,并且將那個 Promise 的接受狀態的回調函數的參數值作為該被返回的Promise的接受狀態回調函數的參數值。
返回一個已經是拒絕狀態的 Promise,那么 then 返回的 Promise 也會成為拒絕狀態,并且將那個 Promise 的拒絕狀態的回調函數的參數值作為該被返回的Promise的拒絕狀態回調函數的參數值。
返回一個未定狀態(pending)的 Promise,那么 then 返回 Promise 的狀態也是未定的,并且它的終態與那個 Promise 的終態相同;同時,它變為終態時調用的回調函數參數與那個 Promise 變為終態時的回調函數的參數是相同的。
將上面的規則簡單總結:
1、如果回調函數中的返回結果是promise對象,則對象狀態由回調函數的執行結果決定
2、如果回到函數中的返回結果為非promise對象(無論是字符串、undefined…只要不是promise對象),對象狀態均為成功,返回值為對象成功調用中的值。
3、throw拋出錯誤,狀態為rejected
let p1 = new Promise((resolve, reject) => { resolve('成功!'); // 或者 // reject(new Error("出錯了!")); }); p1.then(value => { console.log(value); // 成功! }, error => { console.log(error); // 出錯了! });
當狀態由pending變為rejected的時候執行該回調函數,
參數:
回調函數,回調函數的參數為reject函數傳遞過來的值
返回值:
返回一個新的Promise實例對象,因此可以使用鏈式調用。
// 拋出一個錯誤,大多數時候將調用catch方法 let p1 = new Promise(function(resolve, reject) { throw 'Uh-oh!'; }); p1.catch(function(e) { console.log(e); // "Uh-oh!" });
推薦使用catch方法,不要在then方法中定義rejected狀態的回調函數;這是因為使用catch還可以捕獲在then方法執行中存在的錯誤。
// bad promise.then(function(data) { // success }, function(err) { // error }); // good promise.then(function(data) { // success }) .catch(function(err) { // error })
finally() 方法返回一個Promise。在promise結束時,無論結果是fulfilled或者是rejected,都會執行指定的回調函數。這為在Promise是否成功完成后都需要執行的代碼提供了一種方式。這避免了同樣的語句需要在then()和catch()中各寫一次的情況。
參數:
回調函數,不接收任何參數
返回值:
返回一個新的Promise實例對象
let p1 = new Promise(function(resolve, reject) { throw 'Uh-oh!'; }); p1.catch(function(e) { console.log(e); // "Uh-oh!" }).finally(function() { console.log('這段代碼最終都會執行'); });
promise封裝ajax請求
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <title>promise基本使用</title> </head> <body> <script> let promise = new Promise(function(resolve,reject){ // ajax發送異步請求 $.ajax({ // 請求路徑 url:'http://47.100.84.201:8888/carousel/findAll', // 成功回調 success(res){ console.log("成功回調",res); // 通過resolve將成功的回調傳遞出去 //resolve(res); }, // 失敗回調 error(err){ console.log("失敗回調",err); // 通過reject將失敗的回調傳遞出去 //reject(err); } }) }) // 通過promise實例對象的實例方法對數據進行操作 promise .then(res => console.log("接收到resolve傳遞過來的數據" + res)) .catch(err => console.log("接收reject傳遞的數據" + err)) .finally(()=>{ console.log("無論成功還是失敗都會調用!") }) </script> </body> </html>
分析:當在promise實例對象中ajax的兩個回調函數中使用
console.log("成功回調",res)
和console.log("失敗回調",err);
語句反映調用結果(成功或失敗)時,瀏覽器控制臺并不會執行then\catch\finally方法中的內容,因為此時then方法中并沒有接收到來自ajax的res,catch方法有沒有接收到來自ajax的err,所以并不會執行箭頭函數中的語句。
當改為resolve(res);
和reject(err);
時結果如下:
promise層級調用
假設有三個文件first.txt,second.txt,third.txt,讀取文件
第一種方式:
使用普通方式進行層級讀取文件(不推薦),如下:
const fs = require("fs"); fs.readFile('../FILE/first.txt',(err,data1) => { fs.readFile('../FILE/second.txt',(err,data2)=>{ fs.readFile('../FILE/second.txt',(err,data3)=>{ let result = data1 + '\t\n' + data2 + '\t\n' + data3; console.log(result); //... //如果后面還有其他文件呢,會導致回調地獄,代碼會橫向變得很寬很長,并且這里data不能重名,需要不斷的取名字 }); }); });
第二種方式:
使用promise實現,解決縮進問題
const fs = require("fs"); // 初始化promise:讀取第一個文件,使用resolve函數傳遞出去讀取到的數據,用Promise對象接收 const promise = new Promise((resolve,reject)=>{ fs.readFile('../FILE/first.txt',(err,data)=>{ resolve(data); }) }) // 執行回調函數 promise.then(value => { //先看能不能獲取到value值 // console.log(value); //輸出的是buffer // console.log(value.toString()); //可以使用toString方法轉化buffer為正常字符串 // then方法的返回值是一個promise對象,所以這里直接使用return返回一個promise對象 return new Promise((resolve,reject)=>{ // promise中的主要操作也是讀取文件內容 fs.readFile('../FILE/second.txt',(err,data)=>{ // 將讀取到的數據傳遞出去,這里將讀取到的數據放到了數組中,一起傳了出去 // value是初始化時讀取文件first.txt的內容,data指的是當前讀到的文件內容 resolve([value,data]); }) }) //使用鏈式調用方式繼續調用,讀取下一個文件的內容 }).then(value=>{ return new Promise((resolve,reject)=>{ fs.readFile('../FILE/third.txt',(err,data)=>{ // 將讀取到的data通過push方法添加進數組中 // 這里的value是前面傳過來的數組 value.push(data); resolve(value); }) }) }).then(value=>{ // 輸出一一讀取文件后的結果 console.log(value.toString()); // 這是第一個文件,這是第二個文件,這是第三個文件 // 文件間通過逗號分隔 })
雖然目前使用promise的代碼量確實比較多,但卻可以避免代碼橫向增多的問題,不會影響代碼閱讀
定義在Promise中的方法,通過Promise可以直接調用。
Promise.all用于將多個 Promise 實例,包裝成一個新的 Promise 實例
參數:
數組,數組中的元素為Promise實例
返回值:
Promise實例,當p1,p2狀態都為fulfilled時候,該實例的狀態才為fulfilled,此時p1,p2的返回值組成一個數組,傳遞給該實例的回調函數;只要p1,p2的返回值有一個變為rejected,該實例狀態為rejected。
const promise1 = Promise.resolve(3); //該方法用于將現有對象轉化為Promise實例 const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then((values) => { console.log(values); }); // expected output: Array [3, 42, "foo"]
Promise.race用于將多個 Promise 實例,包裝成一個新的 Promise 實例
參數:
數組,數組中的元素為Promise實例
返回值:
Promise實例,當p1,p2之中有一個實例率先改變狀態,該實例的狀態就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給該實例的回調函數。(誰執行的快就返回誰)
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); Promise.race([promise1, promise2]).then((value) => { console.log(value); // Both resolve, but promise2 is faster }); // expected output: "two"
用于將多個 Promise 實例,包裝成一個新的 Promise 實例
參數:
數組,數組中的元素為Promise實例
返回值:
Promise實例,只要p1,p2狀態有一個變為fulfilled,該實例的狀態為fulfilled;p1,p2狀態都變為rejected,該實例狀態才為rejected。
const pErr = new Promise((resolve, reject) => { reject("總是失敗"); }); const pSlow = new Promise((resolve, reject) => { setTimeout(resolve, 500, "最終完成"); }); const pFast = new Promise((resolve, reject) => { setTimeout(resolve, 100, "很快完成"); }); Promise.any([pErr, pSlow, pFast]).then((value) => { console.log(value); // pFast fulfils first }) // expected output: "很快完成"
用于將現有對象轉化為Promise實例
參數:
任意值
const promise1 = Promise.resolve(123); promise1.then((value) => { console.log(value); // expected output: 123 });
返回一個新的 Promise 實例,該實例的狀態為rejected。
參數:
錯誤信息
Promise.reject(new Error('fail')).then(function() { // not called }, function(error) { console.log(error); // Stacktrace });
以上就是“es6 promise有哪些狀態”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。