學習使用Promise

在學習之前,先看一下以往的請求:
試想:
假如,我在寫一個電商網站,然後呢,
當我請求到了頂部導航的數據之後,再請求banner圖的數據,
請求完了banner圖數據之後再去請求側邊欄的數據,
那麼問題來了,我們所寫的代碼格式一定是這樣的:

$.ajax({
	url:'頂部導航.url'
	$.ajax({
		url:'banner圖.url'
		$.ajax({
			url:'側邊欄.url'
		})
	})
})

這個人一種什麼樣的感覺?是不是感覺看起來很繁瑣,很亂~~
那麼我們就想讓代碼變得像這種:

var 頂部導航 = $.ajax({url:'頂部導航.url'})
var banner圖 = $.ajax({url:'banner圖.url'})
var 側邊欄 = $.ajax({url:'側邊欄.url'}) 

當然,我們寫的代碼是不可能變成這種格式,這只是我們的理想模式;我們知道,如果這樣寫的話,變量會保存不下來的;因爲這根本就是同步化的寫法,而我們請求的數據卻是異步的。

那麼!
有沒有一種方法可以讓寫法像同步,而本質是異步化呢?
Promise 就出來了。

//XXX.js文件

function promiseAjax(url){
	let p = new Promise((resolve,reject)=>{
		//第一個參數成功的回調函數
		//第二個參數失敗的回調函數
		
		let xhr = new XMLHttpRequest();
		xhr.open('get',url,true);
		xhr.send();
		xhr.onreadystatechange=function(){
			if(this.readyState===4){
				if(this.status >= 200 && this.status <300 || this.status === 304){
					let res = JSON.parse(this.responseText)
					resolve(res);//成功回調函數的傳參;
				}else{
					reject(this.status)//失敗回調函數的傳參;
				}
			}
		}
	})
	return p
}

//然後調用
let oData = promiseAjax('../data/1.txt')//oData 就是 Promise 的實例
let oData2 = promiseAjax('../data/2.txt')

//new Promise(function(resolve,reject){})
//promise對象 .then 方法接收兩個函數,第一個函數就是resolve,第二個函數是reject

oData.then(function(res){
	console.log(res)//1.txt的內容
},function(error){
	console.log(error)
})

oData2.then(function(res){
    console.log(res)//2.txt的內容
},function(error){
    console.log(error)
})

當然這麼寫就是很麻煩,所以有Promise.all方法

Promise.all([oData,oData2]).then(function(res){
	console.log(res)
},function(err){
	console.log(err)
})

//注意:當oData或者oData2任何一個請求失敗時,則走的是reject;也就是error;


當然上面寫的就是一個臨時用的Pro’mise,如果用的次數很多,那我們還是封裝一個比較完善的方法。用起來更爲方便;

//下面的方法,封裝了一個更爲完善的ajax,僅此而已;
function promiseAjax (json){
	let url = json.url;
	let data = json.data||{};
	let method = json.type || 'get';
	let str = '';
	
	let p = new Promise(function(resolve,reject){
		try{
			var xhr = new XMLHttpRequest();	//這裏不能用let,作用域問題,之前我把這寫成了let,報錯找不到xhr。
		}catch(e){
			var xhr = new ActiveXObject('Microsoft.XMLHTTP');//同上
		}
		if(method.toLowerCase() === 'get'){
			for(let i in data){
				str += i+'='+data[i]+'&'
			}
			xhr.open('get',url+'?'+str+Date.now(),true);
			xhr.send();
		}else if(method.toLowerCase()==='post'){
			xhr.open('post',url,true)
			xhr.setRequestHeader('Conent-type',"application/x-www-form-urlencoded");
			xhr.send(str.substring(0,str.lastIndexOf('&')));
		}
		xhr.onreadystatechange=function(){
			if(this.readyState===4){
				if(this.status>=200&&this.status<300||this.status===304){
					let response;
					try{
						response = JSON.parse(this.responseText);
					}catch(e){
						response = this.responseText;
						console.log(e.message)
					}finally{
						resolve(response)
					}
				}else{
					let erro = new Error();
					erro.status = this.status;
					reject(erro)
				}
				
			}
		};

	})
	return p;
}

//調用:
promiseAjax({
	url:'../data/1.txt',
	type:'get'
}).then(function(res){
	console.log(res)
},function(err){
	console.log(err)
})

用.all方法:
let p1 = promiseAjax({
	url:'../data/1.txt'
})
let p2 =promiseAjax({
	url:'../data/2.txt'
})
Promise.all([p1,p2]).then(function(res){
	console.log(res)
},function(err){
	console.log(err)	
})

需要知道的是JQ3.0以上版本,.ajax()Promise.ajax(),本身就是用的Promise寫的,所以.ajax本身就是一個Promise對象,我們也可以用$.ajax來調用.all .then方法。這裏就不演示了。

感謝閱讀 ,讓我們共同進步。
如果有錯,或者你認爲哪裏有錯,請評論留言,以便於更好的完善這篇文章,方便大家閱讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章