欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript中Promise的簡單使用及其原理詳解

 更新時間:2023年03月23日 11:09:31   作者:Hansel.Wn  
Promise是ES6最重要的特性之一,今天小編就來帶大家一起系統(tǒng)且細(xì)致的研究一下Promise的用法以及原理,感興趣的小伙伴可以學(xué)習(xí)一下哦

Promise是ES6最重要的特性之一,今天來系統(tǒng)且細(xì)致的研究一下Promise的用法以及原理。

按照我往常的理解,Promise是一個構(gòu)造函數(shù),有all、resolve、reject、then、catch等幾個方法,一般情況下,在涉及到異步操作時才會用到Promise。

所以我接下來先new一個Promise對象,并在其中進(jìn)行一些異步操作:

// 使用Promise的時候一般會把它包裹在一個函數(shù)中,并在函數(shù)的最后返回這個Promise對象
function runPro()(
    var a = new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('work done!');
            resolve('success');
        }, 1000);
    });
    return a;
)
runPro()

在上面的代碼中,Promise的構(gòu)造函數(shù)接收一個箭頭函數(shù)作為參數(shù),這個箭頭函數(shù)又有兩個參數(shù),分別是resolve和reject,我在這個箭頭函數(shù)中使用setTimeout進(jìn)行了一些異步操作,異步操作中執(zhí)行了resolve方法,并給resolve方法傳了一個字符串‘success’作為參數(shù)。

執(zhí)行這段代碼會發(fā)現(xiàn),等待了1秒鐘后(因?yàn)槲以趕etTimeout中設(shè)置的等待時間是1000毫秒),輸出了‘work done!’。

這時候并沒有發(fā)現(xiàn)Promise有什么特別的作用,而且resolve和reject這兩個的作用也并沒有體現(xiàn)出來。

之前我們說過Promise這個構(gòu)造函數(shù)上有then、catch方法,在上面的代碼片段中,runPro函數(shù)最后return了一個Promise對象,所以我們可以在runPro函數(shù)執(zhí)行完成之后使用then對Promise對象進(jìn)行進(jìn)一步的操作:

runPro().then((res) => {
    console.log('then:', res);
    //TODO something
});

輸出結(jié)果:

在runPro返回的Promise對象上直接調(diào)用then方法,then方法接收一個函數(shù)作為參數(shù)A,并且這個箭頭函數(shù)也會接收一個參數(shù)B,這個參數(shù)B的值就是前面代碼中resolve方法所傳遞的字符串‘success’。

執(zhí)行代碼,會在1秒后首先輸出‘work done!’,緊接著輸出‘then: success’。

這個時候,就可以簡單的體現(xiàn)出來Promise的作用了,在前面的代碼中,then方法就像是Promise的回調(diào)函數(shù),當(dāng)Promise中的異步操作執(zhí)行完之后,通過鏈?zhǔn)秸{(diào)用的方式執(zhí)行回調(diào)函數(shù)。

這里的關(guān)鍵點(diǎn)就在于鏈?zhǔn)秸{(diào)用上,當(dāng)實(shí)際使用中遇見多層回調(diào)的情況時,Promise的強(qiáng)大之處才能夠體現(xiàn)出來:

function runPro2(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro2');
		}, 1000);
	});
	return a;
};

function runPro3(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro3');
		}, 1000);
	});
	return a;
};

runPro().then(() => {
	return runPro2();
}).then(() => {
	return runPro3();
}).then(() => {
	console.log('all done')
})

到這里為止,大概已經(jīng)明白了,Promise是一個在異步操作過程中,等待其中異步操作完成之后執(zhí)行其回調(diào)函數(shù)的一種結(jié)構(gòu)體。但是其中的原理還是模糊不清,其中resolve和reject這兩個參數(shù)還沒有搞清楚,只知道在前面的幾個代碼片段中都調(diào)用了resolve函數(shù),resolve是做什么的并沒有體現(xiàn)出來。

關(guān)于resolve和reject,我以前的理解是Promise中的異步操作執(zhí)行成功后調(diào)用resolve函數(shù),異步操作執(zhí)行失敗后調(diào)用reject函數(shù),后來發(fā)現(xiàn)這種理解其實(shí)是不準(zhǔn)確的。

在理解這兩個函數(shù)的正確作用之前,我們首先要知道Promise一個重要的特性:狀態(tài)

Promise的狀態(tài):

一個Promise對象的當(dāng)前狀態(tài)必須為以下三種狀態(tài)中的一種:等待(Pending)、完成(Fulfilled)、拒絕(Rejected)。

Pending:

異步操作完成之前,Promise處于等待狀態(tài),這時候的Promise可以遷移至Fulfilled或者Rejected。

Fulfilled:

異步操作完成之后,Promise可能從Pending狀態(tài)遷移至Fulfilled狀態(tài),F(xiàn)ulfilled狀態(tài)的Promise必須擁有一個不可變的終值,并且Fulfilled狀態(tài)的Promise不能遷移為其他狀態(tài)。

Rejected:

異步操作完成之后,Promise可能從Pending狀態(tài)遷移至Rejected狀態(tài),Rejected狀態(tài)的Promise必須擁有一個不可變的拒絕原因,并且Rejected狀態(tài)的Promise不能遷移為其他狀態(tài)。

了解了Promise的三種狀態(tài)之后,我們再來說說resolve和reject這兩個函數(shù)的作用:

  • resolve函數(shù)將Promise設(shè)置為Fulfilled狀態(tài),reject函數(shù)將Promise設(shè)置為Rejected狀態(tài)。
  • 設(shè)置為Fulfilled或者rejected狀態(tài)后,即表示Promise中的異步操作執(zhí)行完成,這時程序就會執(zhí)行then回調(diào)函數(shù)。
  • resolve和reject函數(shù)傳遞的參數(shù),將由then函數(shù)中的箭頭函數(shù)接收。

實(shí)際上,理解Promise的關(guān)鍵點(diǎn)就在于這個狀態(tài),通過維護(hù)狀態(tài)、傳遞狀態(tài)的方法來進(jìn)行及時的回調(diào)。

所以,如下面代碼所示,當(dāng)使用Promise進(jìn)行異步操作的時候,其中有幾個關(guān)鍵點(diǎn)需要特別注意:

在一個函數(shù)中new了一個Promise對象之后,函數(shù)的最后必須把這個Promise對象return出來,否則這個函數(shù)就無法使用then函數(shù)進(jìn)行回調(diào);

異步操作中必須執(zhí)行resolve或者reject函數(shù),否則這個Promise一直處于Pending狀態(tài),代碼就不會執(zhí)行它的回調(diào)函數(shù)。

function runPro(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('resolve');
			console.log('this is runPro');
		}, 1000);
	});
	return a;
}

runPro().then((res) => {
	console.log(res);
})

同樣的道理,當(dāng)異步操作執(zhí)行失敗時,代碼通過執(zhí)行reject函數(shù)的方式,將Promise的狀態(tài)設(shè)置為Rejected,并返回一個拒絕原因:

function runPro(item){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			if(item >= 18) {
				console.log('item 大于 18');
				resolve('一切正常!');
			}else {
				console.log('item 小于 18');
				reject('18+電影不允許放映!');
			}
		}, 1000);
	});
	return a;
}

runPro(13)
.then((res) => {
	console.log('resolve:',res);
},(rej) => {
	console.log('reject:', rej);
})

我們給runPro函數(shù)傳遞不同的參數(shù),runPro接受參數(shù)后進(jìn)行一個異步的判斷,如果這個參數(shù)的值小于18,執(zhí)行reject函數(shù),反之則執(zhí)行resolve函數(shù),異步操作完成之后,執(zhí)行then回調(diào)函數(shù),這里的回調(diào)函數(shù)可以接收兩個箭頭函數(shù)作為參數(shù),分別對應(yīng)了resolve函數(shù)的回調(diào)和reject函數(shù)的回調(diào),這兩個箭頭函數(shù)可以分別拿到resolve和reject傳遞的參數(shù)。

如下面截圖所示,分別給runPro傳遞兩個不同值后,得到了兩種不同的結(jié)果:

catch函數(shù)的用法

在Promise中,catch函數(shù)可以替代reject函數(shù)使用,用來指定接收reject的回調(diào):

function runPro(item){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			if(item >= 18) {
				console.log('item 大于 18');
				resolve('一切正常!');
			}else {
				console.log('item 小于 18');
				reject('18+電影不允許放映!');
			}
		}, 1000);
	});
	return a;
}

runPro(13)
.then((res) => {
	console.log('resolve:',res);
})
.catch((rej) => {
	console.log('catch:', rej);
})

如上面代碼所示,對調(diào)函數(shù)then只有一個箭頭函數(shù)作為參數(shù),這種情況下,這個箭頭函數(shù)就被指定用來接收resolve函數(shù)的回調(diào),而reject函數(shù)的回調(diào)則被catch函數(shù)來接收:

這個地方使用catch函數(shù)來接收reject的回調(diào)有一個優(yōu)點(diǎn),當(dāng)前面的then回調(diào)函數(shù)中出現(xiàn)位置錯誤時,catch函數(shù)可以對錯誤信息進(jìn)行處理,而不會導(dǎo)致代碼報(bào)錯。這個原理和常用的try/catch語句相同。

function runPro(item){
    var a = new Promise((resolve, reject) => {
        setTimeout(() => {
            if(item >= 18) {
                console.log('item 大于 18');
                resolve('一切正常!');
            }else {
                console.log('item 小于 18');
                reject('18+電影不允許放映!');
            }
        }, 1000);
    });
    return a;
}
runPro(19)
.then((res) => {
    console.log(adc); // 這里的adc是一個未定義的變量,當(dāng)代碼執(zhí)行到這里時,會拋出Error信息導(dǎo)致代碼卡死
    console.log('resolve:',res);
}, (rej) => {
    console.log('reject:',rej);
});
runPro(19)
.then((res) => {
    console.log(abc); // 這里的abc是一個未定義的變量,但是由于后邊使用.catch函數(shù)進(jìn)行了異常捕獲,所以程序不會報(bào)錯。而且錯誤原因也會作為參數(shù)傳遞到后面.catch函數(shù)的參數(shù)中
    console.log('resolve:',res);
})
.catch((rej) => {
    console.log('catch:', rej);
})

all函數(shù) / race函數(shù)并行異步操作

Promise的all函數(shù)和race函數(shù)都提供了并行異步操作的能力,二者的區(qū)別在于,當(dāng)這些并行的異步操作耗時不同時,all函數(shù)是在所有的異步操作都執(zhí)行完之后才會執(zhí)行,而race函數(shù)則會在第一個異步操作完成之后立即執(zhí)行。

function runPro1(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro1');
		}, 1000);
	});
	return a;
}
function runPro2(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro2');
		}, 2000);
	});
	return a;
};

function runPro3(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro3');
		}, 3000);
	});
	return a;
};

Promise.all([runPro1(), runPro2(), runPro3()])
.then((res) => {
	console.log('all:', res);
})

function runPro1(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro1');
		}, 1000);
	});
	return a;
}
function runPro2(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro2');
		}, 2000);
	});
	return a;
};

function runPro3(){
	var a = new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('success');
			console.log('this is runPro3');
		}, 3000);
	});
	return a;
};

Promise.races([runPro1(), runPro2(), runPro3()])
.then((res) => {
	console.log('all:', res);
})

如上兩個代碼片段所示,all函數(shù)和race都接收一個數(shù)組作為參數(shù),這個數(shù)組中的值就是我們要進(jìn)行并行執(zhí)行的異步操作。這里我們同樣使用then函數(shù)作為異步操作完成的回調(diào)函數(shù)。

同時我們通過console輸出發(fā)現(xiàn),在race函數(shù)的回調(diào)函數(shù)開始執(zhí)行的時候,另外兩個沒有執(zhí)行完成的異步操作并沒有停止,依舊在執(zhí)行。

到此這篇關(guān)于JavaScript中Promise的簡單使用及其原理詳解的文章就介紹到這了,更多相關(guān)JavaScript Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論