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>
还没有评论,来说两句吧...