Javascript Promise用法

奇迹会出现發表於2024-03-29

構造 Promise

現在我們構造一個promise物件:

new Promise(function (resolve,reject)) {
	//要做的事情...
}

透過新建一個Promise 物件好像並沒有看出它怎樣“更加優雅地書寫複雜的非同步任務”。我們之前遇到的非同步任務都是一次非同步,如果需要多次呼叫非同步函式呢?例如,如果我想分三次輸出字串,第一次間隔1秒,第二次間隔4秒,第三次間隔3秒:

例項

setTimeout(function(){ 

			console.log("First"); 

		setTimeout(function (){ 

				console.1og("Second"); 

			setTimeout(function(){ 

					console.log("Third"); 

			},3000); 

		},4000);

},1000);

使用延遲函式固然可以實現這個功能,但是在一個複雜的程式中,使用函式瀑布實現程式是一件特別繁瑣的事情。

我們現在使用Promise來實現:

例項

new Promise(function(resolve, reject){ 

	setTimeout(function (){ 

		console.log("First"); 

		resolve(); 
		
		},1000); 

}).then(function(){ 

		return new Promise(function(resolve,reject) 

			setTimeout(function (){ 
			
				console.1og("Second"); 
			
				resolve();
            
        	},4000);
     	});
}).then(function(){ 
    
    setTimeout(function (){ 
			
        console.1og("Third");
        
    },3000);
    
});

Promise的使用

Promise 建構函式只有一個引數,是一個函式,這個函式在構造之後會直接被非同步執行,所以我們稱之為起始函式。起始函式包含兩個引數resolve和 reject。

當Promise 被構造時,起始函式會被非同步執行:

例項

new Promise(function(resolve, reject){ 

	console.1og("Run"); 3});

這段程式會直接輸出 Run

resolve 和 reject 都是函式,其中呼叫 resolve 代 表一切正常,reject是出現異常時所呼叫的:

例項

new Promise(function(resolve, reject){ 

	var a=0; 

	var b=1; 

	if (b ==θ)reject("Divide zero"); 

	else resolve(a / b); 
    
}).then(function(value){ 

	console.log("a/b="+value); 

}).catch(function(err){
    
    console.log(err); 

}).finally(function(){ 
    
	console.log("End");
});

這段程式執行結果是:

1 a/b-0 
2 End

Promise 類有 .then().catch()和.finally()三個方 法,這三個方法的引數都是一個函式,then()可以將引數中的函式新增到當前Promise的正常執行序列,catch()則是設定Promise的異常處理序列,finally()是在Promise 執行的最後一定會執 行的序列。.then()傳入的函式會按順序依次執行,有任何異常都會直接跳到catch序列:

例項

new Promise(function(resolve, reject){ 

	console.log(1111); 

	resolve(2222); 

}).then(function (value){ 

	console.1og(value); 

return 3333; 

}).then(function(value){ 

	console.log(value); 

	throw "An error"; 

}).catch(function(err){ 

	console.log(err);
});

執行結果:

1 1111 
2 2222 
3 3333 
4 An error

resolve()中可以放置一個引數用於向下一個then傳遞一個值,then中的函式也可以返回一個值傳遞給 then。但是,如果then中返回的是一個Promise 物件,那麼下一個 then 將相當於對這個返回的Promise 進行操作,這一點從剛才的計時器的例子中可以看出來。

reject()引數中一般會傳遞一個異常給之後的catch函式用於處理異常。

但是請注意以下兩點:

  • resolve 和 reject的作用域只有起始函式,不包括then以及其他序列;
  • resolve 和 reject 並不能夠使起始函式停止執行,別忘了return。

Promise 函式

上述的“計時器”程式看上去比函式瀑布還要長,所以我們可以將它的核心部分寫成一個Promise函式:

例項 :

function print(delay,message){ 

	return new Promise(function (resolve, reject){ 

		setTimeout(function(){ 

			console.log(message); 

			resolve();
			
     	},delay); 

	}); 

}

然後我們就可以放心大膽的實現程式功能了:

例項

print(1000,"First").then(function (){ 

	return print(4000,"Second"); 

}).then(function(){ 

	print(3000,"Third"); 
})

這種返回值為一個 Promise 物件的函式稱作Promise 函式,它常常用於開發基於非同步操作的庫。

相關文章