ES6-Promise

1. Promise的基础

(1)js的异步操作:

     a. ajax请求

    b. 浏览器事件

     c. 定时,setTime setInteval

(2)异步无法避免产生回调函数

<script>
	//定时
	setTime(function(){
	})
	//事件
	add.addEventListener("click",function(){
	})
	//ajax
	xhr.addEventListener("readystartechange",function(){
	})
</script>

(3)回调地狱:回调函数嵌套回调函数

<script>
	//回调函数嵌套回调函数
	//现象
	var xhr = new XMLHttpRuquest();
	xhr.addEventListener("readystartechange",function(){
		xhr.responseText;//想要这个函数再次进行调用,则需要再写个函数

		var xhr = new XMLHttpRuquest();
		xhr.addEventListener("readystartechange",function(){

			//再次调用
			xhr.addEventListener("readystartechange",function(){
			})
		})
	})
	xhr.open();
	xhr.send();
</script>

(4)以上回调函数嵌套函数,代码可读性差,解决方法:Promise,

解决回调地狱

像同步操作那样去执行异步的操作

Promise的构造函数:必须接受一个函数作为参数,函数可以接收参数,例如例子中的resolve

<script>
    //Promise
    let p = new Promise(function(resolve){//接收参数
    	console.log("成功执行");
    	//调用参数,并没有输出进行中...需在下面进行调用
    	resolve("进行中...");//函数
    	console.log("执行完成");
    })
    console.log(p);//Promise { <state>: "fulfilled", <value>: "进行中..." }
    
    //resolve就相当于以下
    p.then(function(data){
    	console.log(data);//输出:进行中...
    })
</script>

2. Promise原理

(1)原理:

a. 一个Promise实例(对象)代表一个异步操作

<script>
    //Promise
    let p = new Promise(function(resolve,reject){//resolve,reject必须叫这个名称,不是自定义的
    	// 必须写异步操作
    	setTimeout(function(){
    		// 相当于函数的调用
    		resolve("执行");
    	},2000)
    })
   
   //相当于函数的声明
    p.then(function(res){
    	console.log(res);//2秒之后输出:执行
    })

</script>

b. promise通过状态去管理异步操作

pendding,进行中

<script>
    //Promise
    let p = new Promise(function(resolve,reject){//resolve,reject必须叫这个名称,不是自定义的
    	// 必须写异步操作
    	setTimeout(function(){
    		// 相当于函数的调用
    		resolve("执行");
    	},2000)
    })

    console.log(p);//Promise { <state>: "pending" }

</script>

fulfilled,已完成

<script> 
   //=============状态fulfilled已完成===========

      let p3 = new Promise(function(resolve,reject){//resolve,reject必须叫这个名称,不是自定义的
    	// 必须写异步操作
    	setTimeout(function(){
    		// 相当于函数的调用
    		resolve("执行fulfilled");
    	},2000)
    })
    setInterval(function(){
    	console.log(p3);
    },3000)//Promise { <state>: "fulfilled", <value>: "执行fulfilled" }

</script>

resolve(),函数执行之后

reject(),函数执行

rejected(),执行失败

<script>
    //=============状态rejected执行失败===========

      let p4 = new Promise(function(resolve,reject){//resolve,reject必须叫这个名称,不是自定义的
    	// 必须写异步操作
    	setTimeout(function(){
    		// 相当于函数的调用
    		// resolve("执行rejected");
    		reject();
    	},2000)
    })
    setInterval(function(){
    	console.log(p4);
    },3000)//Promise { <state>: "rejected" }
</script>

总结:以一例子看

<script>
	
    //Promise
    function timeout(){
    	let randNum = Math.random() * 2;
    	// let p = new Promise(function(resolve,reject){
    	return new Promise(function(resolve,reject){
    		setTimeout(function(){
    			if(randNum > 1){
    				resolve();

    			}else{
    				reject();
    			}

    		},randNum * 1000)
    	});
    }
    // 方法一:先使用setInterval实现

    let p = timeout();
    setInterval(function(){
    	console.log(p);
    },1000)//状态不确定

    //方法二:then()
    timeout.then(function(){
    	console.log("成功");

    },function(){
    	console.log("失败");
    })
   
</script>

3. Promise实例

问题:三个接口:电影排行榜、电影详情内容、电影详情人信息,查找排行榜第一的电影的导演的家乡在哪

解答一:传统

<body>
	<div id="main"></div>
</body>
<script>
	//排行榜
	let url01 = "http://api.unclealan.cn:4100/movie/top";

	// 电影详情
	let url02 = "http://api.unclealan.cn:4100/movie/subject/";

	// 电影人详情
	let url03 = "http://api.unclealan.cn:4100/movie/celebrity/";

	let message = "排行榜第一的电影是:"

	// 1. 排行榜
	let xhr01 = new XMLHttpRequest();
	// 检测是否成功
	xhr01.onload = function(){
		// console.log(xhr01.responseText);//输出一些json字符串
		// 解析
		let resObj = JSON.parse(xhr01.responseText);
		let id = resObj.subjects[0].id;
		console.log(resObj.subjects[0].id);
		console.log(resObj.subjects[0].title);

		message += resObj.subjects[0].title+ ";";


		//2. 电影详情
		let xhr02 = new XMLHttpRequest();
		//检测是否成功
		xhr02.onload = function(){
			let resObj = JSON.parse(xhr02.responseText);
			// console.log(resObj);
			let id =resObj.directors[0].id;
			console.log(id);

			message += "导演是:"+resObj.directors[0].name+ ";";


			//3. 电影详情人
			let xhr03 = new XMLHttpRequest();
			xhr03.onload = function(){

				let resObj = JSON.parse(xhr03.responseText);
				console.log(resObj.born_place);

				message += "老家是:"+resObj.born_place;

				document.querySelector("#main").innerHTML = message;

				// let name = resObj.avatars.born_place;


			}
			xhr03.onerror = function(){
				console.log("请求电影详情人失败");
			}
			xhr03.open("GET",url03+id);//显示http://api.unclealan.cn:4100/subject/:id
			xhr03.send();


		}
		xhr02.onerror = function(){
			console.log("请求电影详情失败");
		}


		xhr02.open("GET",url02+id);//显示http://api.unclealan.cn:4100/subject/:id
		xhr02.send();


	}
	xhr01.onerror = function(){
		console.log("请求电影排行榜失败");
	}

	xhr01.open("GET",url01);
	xhr01.send();                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
</script>

 

解答二:Promise

<body>
   <div id="main"></div>
</body>
<script>
	//1. 排行榜
	let url01 = "http://api.unclealan.cn:4100/movie/top";

	//2. 电影详情
	let url02 = "http://api.unclealan.cn:4100/movie/subject/";

	//3. 电影人详情
	let url03 = "http://api.unclealan.cn:4100/movie/celebrity/";

	let message = "排行榜第一的电影是:"

		// 1. 排行榜
		function getTopInfo(){
			return new Promise(function(resolve,reject){
				let xhr = new XMLHttpRequest();
				xhr.onload = function(){
					resolve(JSON.parse(xhr.responseText));

				}
				xhr.onerror = function(){
					reject("获取电影排行榜失败");
				}
				xhr.open("GET",url01);
				xhr.send();
			})
		}

		//2. 电影详情
		function getMovieInfo(id){
			return new Promise(function(resolve,reject){
				let xhr = new XMLHttpRequest();
				xhr.onload = function(){
					resolve(JSON.parse(xhr.responseText));
				}
				xhr.onerror = function(){
					reject("获取电影信息失败");
				}
				xhr.open("GET",url02+id);
				xhr.send();
				
			})
		}

		//3. 获取导演信息
		function getDirectorInfo(id){
			return new Promise(function(resolve,reject){
				let xhr = new XMLHttpRequest();
				xhr.onload = function(){
					resolve(JSON.parse(xhr.responseText));

				}
				xhr.onerror = function(){
					reject("获取导演信息失败");
				}
				xhr.open("GET",url03+id);
				xhr.send();

			})
		}


		// 1. 排行榜
		getTopInfo().then(function(res){
			console.log(res);
			message += res.subjects[0].title;
			return getMovieInfo(res.subjects[0].id);

		}
		//直接调用第二次异步请求
		// ,function(){
		// 	console.log("请求电影排行榜失败");
		// }
		)


		//2. 电影详情
		.then(function(res){
			message += "导演是:"+res.directors[0].name;
			return getDirectorInfo(res.directors[0].id);

		})

		//3. 获取导演信息
		.then(function(res){
			message += "家乡是:"+res.born_place;
			document.querySelector("#main").innerHTML = message;

		},function(msg){
			console.log(msg);//只写一个reject函数即可
		})
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
</script>

 

解答三:Promise更简洁

<body>
	<div id="main"></div>
</body>
<script>

	//1. 排行榜
	let url01 = "http://api.unclealan.cn:4100/movie/top";

	//2. 电影详情
	let url02 = "http://api.unclealan.cn:4100/movie/subject/";

	//3. 电影人详情
	let url03 = "http://api.unclealan.cn:4100/movie/celebrity/";

	let message = "排行榜第一的电影是:"

	//异步获取接口数据
	function getInfo(url, errmes, id=0){

		//如果传递了id,url拼接id
		if(id !==0){
			url +=id;
		}

		return  new Promise(function(resolve,reject){
			let xhr = new XMLHttpRequest();
			xhr.onload = function(){
				resolve(JSON.parse(xhr.responseText));
			}
			xhr.onerror = function(){
				reject(errMsg);
			}
			xhr.open("GET",url);
			xhr.send();
		})

	}

	getInfo(url01,"获取电影排行榜失败").then(function(res){
		message += res.subjects[0].title;
		return getInfo(url02,"获取电影详情失败",res.subjects[0].id);
	})


	.then(function(res){
		message += "导演是:"+res.directors[0].name;
		return getInfo(url03,"获取导演信息失败",res.directors[0].id);

	})

	.then(function(res){
		message += "家乡是:"+res.born_place;
		document.querySelector("#main").innerHTML = message;
	},function(msg){
		console.log(msg);
	})
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
</script>

4. Promise方法

(1)then()

(2)catch()参数一个回调函数,promise状态为reject时调用,代替then中失败参数

例子:

<script>
	function timeout(){
		let randNum = Math.random() * 2;
		console.log(randNum);
		return new Promise(function(resolve,reject){
			if(randNum > 1){
				resolve();
			}else{
				reject();
			}
		})
	}

	timeout().then(function(){
		console.log("成功");
	})
	.catch(function(){
		console.log("失败");
	})
	                                                         
</script>

(3)all() 参数是数组,数组成员都是多个Promise对象

<script>
	function timeout01(){
		let randNum = Math.floor(Math.random() * 10);//0-9随机整数

		return new Promise(function(resolve,reject){
			setTimeout(function(){
				if(randNum > 5){
					resolve(randNum);
				}else{
					reject("timeout01失败");
				}
			},1000)
			
		})
	}

	function timeout02(){
		let randNum = Math.floor(Math.random() * 10)+10;//10-19随机整数

		return new Promise(function(resolve,reject){
			setTimeout(function(){
				if(randNum > 15){
					resolve(randNum);
				}else{
					reject("timeout02失败");
				}
			},2000)
			
		})
	}


	function timeout03(){
		let randNum = Math.floor(Math.random() * 10)+20;//20-29随机整数

		return new Promise(function(resolve,reject){
			setTimeout(function(){
				if(randNum > 25){
					resolve(randNum);
				}else{
					reject("timeout03失败");
				}
			},3000)
			
		})
	}

	Promise.all([timeout01(), timeout02(), timeout03()]).then(function(res){
		console.log(res);//Array [ 6, 18, 29 ]
	})
	.catch(function(res){
		console.log(res);
	})
	                                                         
</script>

(4) race() 参数是数组,数组成员都是Promise对象,输出最先完成的异步操作

例子一:

<script>
	function loadImage(){
		return new Promise(function(resolve,reject){
			let img = new Image();
			img.src = "http://c.hiphotos.baidu.com/image/pic/item/0824ab18972bd407cf293db177899e510eb30994.jpg";

			img.onload =function(){
				resolve(img);
			}
			img.onerror = function(){
				reject("图片加载失败");
			}
			
		})
	}

	function timeout(){

		return new Promise(function(resolve,reject){
			setTimeout(function(){
				reject("图片请求失败");
			},6000)
			
		})
	}

	Promise.race([loadImage(), timeout()]).then(function(res){
		document.body.appendChild(res);
	})
	.catch(function(res){
		console.log(res);//如果没用图片,直接输出timeout中“图片请求失败”
	})
	                                                         
</script>

all()和race()区别:

all()所有的Promise对象状态改变,才执行then;

race()执行最快的Promise,最快的Promise状态改变,其他Promise停止

5. JQuery中使用Promise

<script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
<body>
	<div id="main"></div>
<script>
	//查找排行榜第一的电影的导演的家乡在哪

	//1. 排行榜
	let url01 = "http://api.unclealan.cn:4100/movie/top";

	//2. 电影详情
	let url02 = "http://api.unclealan.cn:4100/movie/subject/";

	//3. 电影人详情
	let url03 = "http://api.unclealan.cn:4100/movie/celebrity/";

	let message = "排行榜第一是:"


	// 1. 排行榜
		$.ajax({
			url: url01,
			dataType: "json"

		}).then(function(res){
			message += res.subjects[0].title;
				return $.ajax({
					//2. 电影详情
					url: url02+res.subjects[0].id,
					dataType: "json"

			}).then(function(res){
				message += ";导演是:"+res.directors[0].name;
				return $.ajax({
					//3. 电影人详情
					url: url03+res.directors[0].id,
					dataType: "json"
				})

			}).then(function(res){
				message += ";导演的家乡是:"+res.born_place;
				document.querySelector("#main").innerHTML = message;
			}).catch(function(){
				console.log("请求失败");
			})

		})
</script>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值