JavaScript-Promise的使用及详细解释
案例
使用多种方法实现以下案例
案例目标
- “你好”----2秒后输出
- “你笑起来真好看你”----3.5秒后输出
- “你能做我的男朋友吗”----1.5秒后输出
第一种—setTimeout嵌套
- 使用嵌套的setTimeout定时器来实现
- 缺点:层级太深,需要嵌套,如果项目大,显得复杂
var arr = [
"你好",
"你笑起来真好看你",
"你能做我的男朋友吗"
]
setTimeout(function() {
console.log(arr[0]);
setTimeout(function() {
console.log(arr[1]);
setTimeout(function() {
console.log(arr[2]);
},1500)
},3500)
},2000)
第二种—封装函数
- 通过回调函数调用
- 缺点:如果层级很多,会出现回调地狱
// 第二种 封装函数等方法
function say(msg,time,callback) {
setTimeout(function() {
console.log(msg);
if(callback) {
callback();
}
},time);
}
// 调用
say("你好",2000,function() {
say("你笑起来真好看",3500,function() {
say("你能做我男朋友吗?",1500)
})
})
Promise详解
Promise
承诺 (异步延时调用-层级扁平)resolve
兑现承诺reject
拒绝兑现then()
获取兑现结果catch()
获取拒绝的原因
小案例
function bigHouse() {
return new Promise(function(resolve,reject) {
setTimeout(function() {
var n = Math.random();
if(n > .5) {
// 想要兑现承诺,但是还没有实现
resolve("我已经在CBD买了三层大洋楼,前面花园,后面游泳池,顶层停机坪");
}else {
reject("今年疫情原因,业绩不好");
}
})
})
}
bigHouse()
.then( res => {
console.log("兑现承诺的结果");
})
.catch( err => {
console.log("拒绝兑现承诺的原因");
})
第三种—使用Promise来实现最开始的案例
- 实现了延期调用—避免调用
// 第三种
function say(msg,time) {
return new Promise(function(resolve,reject) {
setTimeout(function() {
resolve(msg);
},time)
})
}
say("你好",2000)
.then( res => {
console.log(res);
return say("你笑起来真好看",3500);
})
.then( res => {
console.log(res);
return say("你能做我男朋友吗?",3500);
})
.then( res => {
console.log(res);
})
Promise—具体使用的案例
第一版—点击按钮显示图片
<body>
<button id="btn">加载</button>
</body>
<script type="text/javascript">
var pics = [
"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7bc54a61b927dd8c54ddd39a0acf0254.jpg?w=632&h=340",
"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/94c74e01afe50a86c3a87ff030b85781.jpg?w=632&h=340",
"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/816a66edef10673b4768128b41804cae.jpg?w=632&h=340"
]
// 使用Promise 写法,单击按钮 btn,加载显示pics李米娜的第一张图片
function loadImage(url) {
// 返回一个promise对象
return new Promise(function(resolve,reject) {
// 创建一个图片节点
var img = document.createElement("img");
// 设置url
img.src = url;
// 当加载成功时返回图片
img.onload = function() {resolve(img)};
// 当家在失败时,返回失败的原因
img.onerror = function(e) {reject(e)};
})
}
// 触发事件,调用事件
btn.onclick = function() {
loadImage(pics[0])
.then( res => {
// 将返回的图片元素加载到数据中
document.body.append(res);
})
.catch( err => {
console.log(err);
})
}
</script>
第二版—加载出第一张之后在加载其他,依次加载
- 套用promise
- 重复返回
var pics = [
"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7bc54a61b927dd8c54ddd39a0acf0254.jpg?w=632&h=340",
"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/94c74e01afe50a86c3a87ff030b85781.jpg?w=632&h=340",
"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/816a66edef10673b4768128b41804cae.jpg?w=632&h=340"
]
// 使用Promise 写法,单击按钮 btn,加载显示pics李米娜的第一张图片
function loadImage(url) {
// 返回一个promise对象
return new Promise(function(resolve,reject) {
// 创建一个图片节点
var img = document.createElement("img");
// 设置url
img.src = url;
// 当加载成功时返回图片
img.onload = function() {resolve(img)};
// 当家在失败时,返回失败的原因
img.onerror = function(e) {reject(e)};
})
}
loadImage(pics[0])
.then( res => {
// 将返回的图片元素加载到数据中
document.body.append(res);
// 再次返回这个事件
return loadImage(pics[1]);
})
// 因为上个成功回调,重新返回了一个promise所以再次需要成功的回调
.then( res => {
// 将返回的图片元素加载到数据中
document.body.append(res);
return loadImage(pics[2]);
})
.then( res => {
// 将返回的图片元素加载到数据中
document.body.append(res);
})
.catch( err => {
console.log(err);
})
第三版—图片中谁先加载完成,谁就先显示
Promise.race()
Promise.race([所用加载的数据]).then( res => {成功的承诺结果回调}).catch( err => {失败的承诺原因回调})
// 第三版 图片中谁先加载完成,谁就先显示
Promise.race([loadImage(pics[0]),loadImage(pics[1]),loadImage(pics[2])])
.then( res => {
document.body.append(res);
});
第四版—等待图片全部加载完毕,所有图片一起显示
Promise.all()
Promise.all([所用加载的数据]).then( res => {成功的承诺结果回调}).catch( err => {失败的承诺原因回调})
Promise.all([loadImage(pics[0]),loadImage(pics[1]),loadImage(pics[2])])
.then( res => {
for(var img in res) {
document.body.append(res[img]);
}
});
封装Jsonp
- 封装Jsonp用到了Promise
- 参考
封装-Jsonp