js中關于promise的用法解讀
一、概述
Promise是異步編程的一種解決方案,可以替代傳統(tǒng)的解決方案--回調函數(shù)和事件。
ES6統(tǒng)一了用法,并原生提供了Promise對象。
作為對象,Promise有以下兩個特點:
- (1)對象的狀態(tài)不受外界影響。
- (2)一旦狀態(tài)改變了就不會再變,也就是說任何時候Promise都只有一種狀態(tài)。
二、Promise的狀態(tài)
Promise有三種狀態(tài),分別是 Pending (進行中)、Resolved (已完成)、Rejected (已失敗)。
Promise從Pending狀態(tài)開始,如果成功就轉到成功態(tài),并執(zhí)行resolve回調函數(shù);如果失敗就轉到失敗狀態(tài)并執(zhí)行reject回調函數(shù)。
三、基本用法
可以通過Promise的構造函數(shù)創(chuàng)建Promise對象
var promise = new Promise((resolve,reject) => {
? setTimeout(()=>{
? ? console.log("hello world")
}, 2000)
})Promise構造函數(shù)接受一個函數(shù)作為參數(shù),該函數(shù)的兩個參數(shù)是 resolve ,reject,它們由JavaScript引擎提供。
其中 resolve 函數(shù)的作用是當Promise對象轉移到成功,調用resolve并將操作結果作為其參數(shù)傳遞出去;reject 函數(shù)的作用是當Promise對象的狀態(tài)變?yōu)槭r,將操作報出的錯誤作為參數(shù)傳遞出去。
如下代碼:
function greet(){
? var promise = new Promise(function(resolve,reject){
? ? var greet = "hello world"
? ? resolve(greet)
})
? return promise
}
greet().then(v=>{
? console.log(v)//*
})上面的 * 行的輸出就是greet的值,也就是 resolve() 傳遞出來的參數(shù)。
注意:創(chuàng)建一個Promise對象會立即執(zhí)行里面的代碼,所以為了更好的控制代碼的運行時刻,可以將其包含在一個函數(shù)中,并將這個Promise作為函數(shù)的返回值。
四、Promise的then方法
promise的then方法帶有一下三個參數(shù):成功的回調,失敗的回調,前進的回調。
一般情況下只需要實現(xiàn)第一個,后面的是可選的。
Promise中最為重要的狀態(tài),通過then的狀態(tài)傳遞可以實現(xiàn)的回調函數(shù)鏈式操作的實現(xiàn)。
先執(zhí)行以下代碼:
function greet () {
? var promise = new Promise (function(resolve, reject){
? ? var greet = "hello world"
? ? resolve(greet)
? })
? return promise
}
var p = greet().then(v => {
? console.log(v) ?// Promise { <pending> }
})
console.log(p) ?// hello world從中可以看出promise執(zhí)行then還是一個promise,并且Promise的執(zhí)行是異步的。
因為 hello world 在最后一條輸出語句的前面就打印出來了,且Promise的狀態(tài)為pending(進行中)。
因為Promise執(zhí)行then后還是Promise,所以就可以根據(jù)這一特性,不斷的鏈式調用回調函數(shù)。
下面是一個例子:
function greet () {
? var promise = new Promise(function (resolve, reject){
? ? var greeet = "hello world"
? ? resolve(greet)
? })
? return promise
}
greet().then(v => {
? console.log(v+1)
? return v
})
.then (v => {
? console.log(v+2)
? return v
})
.then (v => {
? console.log(v+3)
})五、Promise的其他方法
reject用法
reject的作用就是把Promise的狀態(tài)從pending置為rejected,這樣在then中就能捕捉到reject的回調函數(shù)
function judgeNumber (num) {
? var promise = new Promise (function(resolve, reject) {
? ? num = 5
? ? if(num < 5){
? ? ? resolve("num小于5,值為" + num)
? ? } else {
? ? ? reject("num不小于5,值為" + num)
? ? }
? })
? return promise
}
?
judgeNumber().then(
? function (message) {
? ? console.log(message)
? },
? funtion (message) {
? ? console.log(message)
? }
).then 后包含有兩個方法,前一個執(zhí)行resolve回調的參數(shù),后一個執(zhí)行reject回調的參數(shù)
catch用法
function judgeNumber(num){
? ? var promise1 = new Promise(function(resolve,reject){
? ? ? ? num =5;
? ? ? ? if(num<5){
? ? ? ? ? ? resolve("num小于5,值為:"+num);
? ? ? ? }else{
? ? ? ? ? ? reject("num不小于5,值為:"+num);
? ? ? ? }
? ? });
? ? return promise1;
}
?
judgeNumber().then(
? ? function(message){
? ? ? ? console.log(message);
? ? }
)
.catch(function(message){
? ? console.log(message);
})這個時候catch執(zhí)行的是和reject一樣的,也就是說如果Promise的狀態(tài)變?yōu)閞eject時,會被catch捕捉到,不過需要特別注意的是如果前面設置了reject方法的回調函數(shù),則catch不會捕捉到狀態(tài)變?yōu)閞eject的情況。
catch還有一點不同的是,如果在resolve或者reject發(fā)生錯誤的時候,會被catch捕捉到,這與java,c++的錯誤處理時一樣的,這樣就能避免程序卡死在回調函數(shù)中了。
all用法
Promise的all方法提供了并行執(zhí)行異步操作的能力,在all中所有異步操作結束后才執(zhí)行回調。
function p1(){
? ? var promise1 = new Promise(function(resolve,reject){
? ? ? ? console.log("p1的第一條輸出語句");
? ? ? ? console.log("p1的第二條輸出語句");
? ? ? ? resolve("p1完成");
? ? })
? ? return promise1;
}
?
function p2(){
? ? var promise2 = new Promise(function(resolve,reject){
? ? ? ? console.log("p2的第一條輸出語句");
? ? ? ? setTimeout(()=>{console.log("p2的第二條輸出語句");resolve("p2完成")},2000);
?
? ? })
? ? return promise2;
}
?
function p3(){
? ? var promise3 = new Promise(function(resolve,reject){
? ? ? ? console.log("p3的第一條輸出語句");
? ? ? ? console.log("p3的第二條輸出語句");
? ? ? ? resolve("p3完成")
? ? });
? ? return ?promise3;
}
?
Promise.all([p1(),p2(),p3()]).then(function(data){
? ? console.log(data);
})race用法
在all中的回調函數(shù)中,等到所有的Promise都執(zhí)行完,再來執(zhí)行回調函數(shù),race則不同它等到第一個Promise改變狀態(tài)就開始執(zhí)行回調函數(shù)。
將上面的`all`改為`race`,得到
Promise.race([p1(),p2(),p3()]).then(function(data){
? ? console.log(data);
})這里還需要注意一個問題,promise的執(zhí)行時異步的,比如下面這樣:
var i
?
var promise = new Promise(function(resolve,reject){
? ? resolve("hello");
})
?
promise.then(data=>{
? ? i = 2;
?
})
console.log(i);? ? ? ?得到的結果是undefined,這不是因為promise不能改變外部的值,而是因為當執(zhí)行console.log(i)時,then()方法還沒執(zhí)行完。
如果你將console.log(i)延遲輸出就可以得到正確的結果:
setTimeout(()=>console.log(i),1000);
所以不要在promise后面執(zhí)行一些依賴promise改變的代碼,因為可能promise中的代碼并未執(zhí)行完,或者你可以將其延遲輸出。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用postMesssage()實現(xiàn)iframe跨域頁面間的信息傳遞
這篇文章主要介紹了使用postMesssage()實現(xiàn)iframe跨域頁面間的信息傳遞 的相關資料,需要的朋友可以參考下2016-03-03
javascript addLoadEvent函數(shù)說明
網頁加載完整后會觸發(fā)一個onload事件,默認地一個事件只能和一個函數(shù)綁定。2010-01-01
在for循環(huán)中l(wèi)ength值是否需要緩存
這篇文章主要介紹了在for循環(huán)中l(wèi)ength值是否需要緩存,需要的朋友可以參考下2015-07-07
JavaScript+Node.js寫一款markdown解析器
這篇文章主要介紹了利用JavaScript和Node.js寫一款markdown解析器,首先編寫getHtml函數(shù),傳入markdown文本字符串,下面更多詳細內容,需要的小伙伴可以參考一下2022-02-02

