溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

es6 promise有哪些狀態(tài)

發(fā)布時(shí)間:2022-05-20 16:01:33 來源:億速云 閱讀:266 作者:iii 欄目:web開發(fā)

今天小編給大家分享一下es6 promise有哪些狀態(tài)的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

有3種狀態(tài):1、pending,表示正在進(jìn)行中,該狀態(tài)會(huì)進(jìn)行初始化;2、fulfilled,表示已成功;3、rejected,表示已失敗,會(huì)觸發(fā)后續(xù)的catch回調(diào)函數(shù)。promise的狀態(tài)發(fā)生改后就會(huì)凝固,不會(huì)再變,會(huì)一直保持這個(gè)結(jié)果。

本教程操作環(huán)境:windows7系統(tǒng)、ECMAScript 6版、Dell G3電腦。

Promise簡(jiǎn)介

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù)和事件)更合理和更強(qiáng)大。

所謂Promise,簡(jiǎn)單說就是一個(gè)容器,里面保存著某個(gè)未來才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。

從語(yǔ)法上說,Promise 是一個(gè)構(gòu)造函數(shù),從它可以獲取異步操作的消息。

Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理。有了Promise對(duì)象,就可以將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)。

Promise對(duì)象提供統(tǒng)一的接口,使得控制異步操作更加容易。

我們知道,es5是單線程語(yǔ)言,語(yǔ)句執(zhí)行順序由上往下,而項(xiàng)目前端對(duì)接后端時(shí),需要用到ajax,而ajax是異步的,可能導(dǎo)致數(shù)據(jù)的交互產(chǎn)生延遲,不利于編程。而promise函數(shù)可以很好的解決這個(gè)問題。

Promise實(shí)例化

Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolvereject。而這兩個(gè)參數(shù)是兩個(gè)函數(shù),由 JavaScript 引擎提供。

Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài): pending(進(jìn)行中)fulfilled(已成功)rejected(已失?。?/strong>。

  • 初始化,狀態(tài):pending

  • 當(dāng)調(diào)用resolve(成功),狀態(tài):pengding=>fulfilled

  • 當(dāng)調(diào)用reject(失敗),狀態(tài):pending=>rejected

狀態(tài)發(fā)生改變之后就凝固了,不會(huì)再變了,會(huì)一直保持這個(gè)結(jié)果,這時(shí)就稱為 resolved(已定型)

狀態(tài)變化:

1、pending -> resolved

2、pending -> rejected

狀態(tài)的表現(xiàn)

  • pending狀態(tài)不會(huì)觸發(fā)then和catch

  • resolved狀態(tài)會(huì)觸發(fā)后續(xù)的then回調(diào)函數(shù)

  • rejected狀態(tài)會(huì)觸發(fā)后續(xù)的catch回調(diào)函數(shù)

then和catch改變狀態(tài)

  • then正常情況下會(huì)返回resolved,報(bào)錯(cuò)則返回rejected

  • catch正常情況下會(huì)返回resolved,報(bào)錯(cuò)則返回rejected

const promise = new Promise(function(resolve,reject){
	//...some code
	if(/*異步操作成功*/){
		resolve(value);
		// 狀態(tài)由pending變?yōu)閒ulfilled
	}else{
		reject(error);
		// 狀態(tài)由pending變?yōu)閞ejected
	}
})

例如:

<!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>測(cè)試</title>
</head>
<body>
    <script>
        let promise = new Promise(function (resolve, reject) {
            if (3 < 5) {
                resolve("是正確的");
            } else {
                reject("是錯(cuò)誤的");
            }
        })
        console.log(promise);
    </script>
</body>
</html>

結(jié)果:

es6 promise有哪些狀態(tài)

Promise的原型方法

定義在Promise.prototype中的方法,通過Promise實(shí)例可以直接調(diào)用。

1、Promise.prototype.then()

當(dāng)狀態(tài)由pending變?yōu)閒ulfilled的時(shí)候執(zhí)行該回調(diào)函數(shù),

參數(shù):

最多需要有兩個(gè)參數(shù),Promise 的成功和失敗情況的回調(diào)函數(shù)。

返回值:

返回一個(gè)新的Promise實(shí)例對(duì)象,因此可以使用鏈?zhǔn)秸{(diào)用。

當(dāng)一個(gè) Promise 完成(fulfilled)或者失?。╮ejected)時(shí),返回函數(shù)將被異步調(diào)用(由當(dāng)前的線程循環(huán)來調(diào)度完成)。具體的返回值依據(jù)以下規(guī)則返回。如果 then 中的回調(diào)函數(shù):

  • 返回了一個(gè)值,那么 then 返回的 Promise 將會(huì)成為接受狀態(tài),并且將返回的值作為接受狀態(tài)的回調(diào)函數(shù)的參數(shù)值。

  • 沒有返回任何值,那么 then 返回的 Promise 將會(huì)成為接受狀態(tài),并且該接受狀態(tài)的回調(diào)函數(shù)的參數(shù)值為 undefined。

  • throw拋出一個(gè)錯(cuò)誤,那么 then 返回的 Promise 將會(huì)成為拒絕狀態(tài),并且將拋出的錯(cuò)誤作為拒絕狀態(tài)的回調(diào)函數(shù)的參數(shù)值。

  • 返回一個(gè)已經(jīng)是接受狀態(tài)的 Promise,那么 then 返回的 Promise 也會(huì)成為接受狀態(tài),并且將那個(gè) Promise 的接受狀態(tài)的回調(diào)函數(shù)的參數(shù)值作為該被返回的Promise的接受狀態(tài)回調(diào)函數(shù)的參數(shù)值。

  • 返回一個(gè)已經(jīng)是拒絕狀態(tài)的 Promise,那么 then 返回的 Promise 也會(huì)成為拒絕狀態(tài),并且將那個(gè) Promise 的拒絕狀態(tài)的回調(diào)函數(shù)的參數(shù)值作為該被返回的Promise的拒絕狀態(tài)回調(diào)函數(shù)的參數(shù)值。

  • 返回一個(gè)未定狀態(tài)(pending)的 Promise,那么 then 返回 Promise 的狀態(tài)也是未定的,并且它的終態(tài)與那個(gè) Promise 的終態(tài)相同;同時(shí),它變?yōu)榻K態(tài)時(shí)調(diào)用的回調(diào)函數(shù)參數(shù)與那個(gè) Promise 變?yōu)榻K態(tài)時(shí)的回調(diào)函數(shù)的參數(shù)是相同的。

將上面的規(guī)則簡(jiǎn)單總結(jié):
1、如果回調(diào)函數(shù)中的返回結(jié)果是promise對(duì)象,則對(duì)象狀態(tài)由回調(diào)函數(shù)的執(zhí)行結(jié)果決定
2、如果回到函數(shù)中的返回結(jié)果為非promise對(duì)象(無論是字符串、undefined…只要不是promise對(duì)象),對(duì)象狀態(tài)均為成功,返回值為對(duì)象成功調(diào)用中的值。
3、throw拋出錯(cuò)誤,狀態(tài)為rejected

let p1 = new Promise((resolve, reject) => {
	resolve('成功!');
	// 或者
	// reject(new Error("出錯(cuò)了!"));
});

p1.then(value => {
	console.log(value); // 成功!
}, error => {
	console.log(error); // 出錯(cuò)了!
});

2、Promise.prototype.catch()

當(dāng)狀態(tài)由pending變?yōu)閞ejected的時(shí)候執(zhí)行該回調(diào)函數(shù),
參數(shù):
回調(diào)函數(shù),回調(diào)函數(shù)的參數(shù)為reject函數(shù)傳遞過來的值
返回值:
返回一個(gè)新的Promise實(shí)例對(duì)象,因此可以使用鏈?zhǔn)秸{(diào)用。

// 拋出一個(gè)錯(cuò)誤,大多數(shù)時(shí)候?qū)⒄{(diào)用catch方法
let p1 = new Promise(function(resolve, reject) {
	throw 'Uh-oh!';
});

p1.catch(function(e) {
	console.log(e); // "Uh-oh!"
});

推薦使用catch方法,不要在then方法中定義rejected狀態(tài)的回調(diào)函數(shù);這是因?yàn)槭褂胏atch還可以捕獲在then方法執(zhí)行中存在的錯(cuò)誤。

 // bad
promise.then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise.then(function(data) { 
    // success
  })
  .catch(function(err) {
    // error
  })

3、Promise.prototype.finally()

finally() 方法返回一個(gè)Promise。在promise結(jié)束時(shí),無論結(jié)果是fulfilled或者是rejected,都會(huì)執(zhí)行指定的回調(diào)函數(shù)。這為在Promise是否成功完成后都需要執(zhí)行的代碼提供了一種方式。這避免了同樣的語(yǔ)句需要在then()和catch()中各寫一次的情況。

參數(shù):

回調(diào)函數(shù),不接收任何參數(shù)

返回值:

返回一個(gè)新的Promise實(shí)例對(duì)象

let p1 = new Promise(function(resolve, reject) {
	throw 'Uh-oh!';
});
p1.catch(function(e) {
	console.log(e); // "Uh-oh!"
}).finally(function() { 
	console.log('這段代碼最終都會(huì)執(zhí)行'); 
});
  • promise封裝ajax請(qǐng)求

<!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發(fā)送異步請(qǐng)求
            $.ajax({
                // 請(qǐng)求路徑
                url:'http://47.100.84.201:8888/carousel/findAll',
                // 成功回調(diào)
                success(res){
                    console.log("成功回調(diào)",res);
                    
                    // 通過resolve將成功的回調(diào)傳遞出去
                    //resolve(res);
                },
                // 失敗回調(diào)
                error(err){
                    console.log("失敗回調(diào)",err);
                    
                    // 通過reject將失敗的回調(diào)傳遞出去
                    //reject(err);
                }
            })
        })

        // 通過promise實(shí)例對(duì)象的實(shí)例方法對(duì)數(shù)據(jù)進(jìn)行操作
        promise
        .then(res => console.log("接收到resolve傳遞過來的數(shù)據(jù)" + res))
        .catch(err => console.log("接收reject傳遞的數(shù)據(jù)" + err))
        .finally(()=>{
            console.log("無論成功還是失敗都會(huì)調(diào)用!")
        })
    </script> 
</body>
</html>

分析:當(dāng)在promise實(shí)例對(duì)象中ajax的兩個(gè)回調(diào)函數(shù)中使用console.log("成功回調(diào)",res)console.log("失敗回調(diào)",err);語(yǔ)句反映調(diào)用結(jié)果(成功或失?。r(shí),瀏覽器控制臺(tái)并不會(huì)執(zhí)行then\catch\finally方法中的內(nèi)容,因?yàn)榇藭r(shí)then方法中并沒有接收到來自ajax的res,catch方法有沒有接收到來自ajax的err,所以并不會(huì)執(zhí)行箭頭函數(shù)中的語(yǔ)句。
es6 promise有哪些狀態(tài)
當(dāng)改為resolve(res);reject(err);時(shí)結(jié)果如下:
es6 promise有哪些狀態(tài)

  • promise層級(jí)調(diào)用
    假設(shè)有三個(gè)文件first.txt,second.txt,third.txt,讀取文件
    第一種方式:
    使用普通方式進(jìn)行層級(jí)讀取文件(不推薦),如下:

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);
            //...
            //如果后面還有其他文件呢,會(huì)導(dǎo)致回調(diào)地獄,代碼會(huì)橫向變得很寬很長(zhǎng),并且這里data不能重名,需要不斷的取名字
        });
    });
});

第二種方式:

使用promise實(shí)現(xiàn),解決縮進(jìn)問題

const fs = require("fs");
// 初始化promise:讀取第一個(gè)文件,使用resolve函數(shù)傳遞出去讀取到的數(shù)據(jù),用Promise對(duì)象接收
const promise = new Promise((resolve,reject)=>{
    fs.readFile('../FILE/first.txt',(err,data)=>{
        resolve(data);
    })
})

// 執(zhí)行回調(diào)函數(shù)
promise.then(value => {
    //先看能不能獲取到value值
    // console.log(value); //輸出的是buffer
    // console.log(value.toString()); //可以使用toString方法轉(zhuǎn)化buffer為正常字符串
   
    // then方法的返回值是一個(gè)promise對(duì)象,所以這里直接使用return返回一個(gè)promise對(duì)象
    return new Promise((resolve,reject)=>{
        // promise中的主要操作也是讀取文件內(nèi)容
        fs.readFile('../FILE/second.txt',(err,data)=>{
            // 將讀取到的數(shù)據(jù)傳遞出去,這里將讀取到的數(shù)據(jù)放到了數(shù)組中,一起傳了出去
            // value是初始化時(shí)讀取文件first.txt的內(nèi)容,data指的是當(dāng)前讀到的文件內(nèi)容
            resolve([value,data]);
        })
    })
    //使用鏈?zhǔn)秸{(diào)用方式繼續(xù)調(diào)用,讀取下一個(gè)文件的內(nèi)容
}).then(value=>{
    return new Promise((resolve,reject)=>{
        fs.readFile('../FILE/third.txt',(err,data)=>{
            // 將讀取到的data通過push方法添加進(jìn)數(shù)組中
            // 這里的value是前面?zhèn)鬟^來的數(shù)組
            value.push(data);
            resolve(value);
        })
    })
}).then(value=>{
    // 輸出一一讀取文件后的結(jié)果
    console.log(value.toString()); // 這是第一個(gè)文件,這是第二個(gè)文件,這是第三個(gè)文件
    // 文件間通過逗號(hào)分隔
})

雖然目前使用promise的代碼量確實(shí)比較多,但卻可以避免代碼橫向增多的問題,不會(huì)影響代碼閱讀

靜態(tài)方法

定義在Promise中的方法,通過Promise可以直接調(diào)用。

1、Promise.all([p1,p2])

Promise.all用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例
參數(shù):
數(shù)組,數(shù)組中的元素為Promise實(shí)例
返回值:
Promise實(shí)例,當(dāng)p1,p2狀態(tài)都為fulfilled時(shí)候,該實(shí)例的狀態(tài)才為fulfilled,此時(shí)p1,p2的返回值組成一個(gè)數(shù)組,傳遞給該實(shí)例的回調(diào)函數(shù);只要p1,p2的返回值有一個(gè)變?yōu)閞ejected,該實(shí)例狀態(tài)為rejected。

const promise1 = Promise.resolve(3); //該方法用于將現(xiàn)有對(duì)象轉(zhuǎn)化為Promise實(shí)例
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"]

2、Promise.race([p1,p2])

Promise.race用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例
參數(shù):
數(shù)組,數(shù)組中的元素為Promise實(shí)例
返回值:
Promise實(shí)例,當(dāng)p1,p2之中有一個(gè)實(shí)例率先改變狀態(tài),該實(shí)例的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise 實(shí)例的返回值,就傳遞給該實(shí)例的回調(diào)函數(shù)。(誰(shuí)執(zhí)行的快就返回誰(shuí))

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"

3、Promise.any([p1,p2])

用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例

參數(shù):

數(shù)組,數(shù)組中的元素為Promise實(shí)例

返回值:

Promise實(shí)例,只要p1,p2狀態(tài)有一個(gè)變?yōu)閒ulfilled,該實(shí)例的狀態(tài)為fulfilled;p1,p2狀態(tài)都變?yōu)閞ejected,該實(shí)例狀態(tài)才為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: "很快完成"

4、Promise.resolve()

用于將現(xiàn)有對(duì)象轉(zhuǎn)化為Promise實(shí)例

參數(shù):

任意值

const promise1 = Promise.resolve(123);
promise1.then((value) => {
	console.log(value);
	// expected output: 123
});

5、Promise.reject()

返回一個(gè)新的 Promise 實(shí)例,該實(shí)例的狀態(tài)為rejected。

參數(shù):

錯(cuò)誤信息

Promise.reject(new Error('fail')).then(function() {
	// not called
}, function(error) {
	console.log(error); // Stacktrace
});

以上就是“es6 promise有哪些狀態(tài)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI