目录
了解Promise
Promise :ES6提供的一个构造函数,处理异步事件。接收了一个参数为函数,传入resolve,reject两个参数。resolve为异步操作成功后执行的回调函数,reject为异步操作失败后执行的回调函数。Promise对象上有then,catch方法。例子:
function snycA(){
const promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行完成');
resolve('异步数据1');
},2000)
})
return promise
}
snycA().then((response)=>{
console.log(response);
})
输出的结果为:
Emmmmm...然而这种操作不就跟平时我们使用回调函数(将回调函数作为参数传入函数里,函数里面嵌套函数,等函数执行完成再去执行嵌套函数,就叫回调函数啦)一样了吗?下面的例子就是用回调函数实现上面所实现的效果:
//将callback作为一个参数传入函数中,待函数执行完成再执行回调函数
function syncA(callback){
setTimeout(()=>{
console.log("执行完成");
callback('回调数据1');
},2000)
}
syncA((data)=>{
console.log(data)
})
输出的结果为:
虽然回调函数也能实现同样的效果,但是,如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?总不能再定义一个callback2,然后给callback传进去吧。而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。
Promiseの链式操作及Resolve的用法
promise能层层简化多层回调的写法,而Promise的精髓在于维护状态,传递状态。下面来简单实现一下
function syncA(){
const P = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行syncA');
resolve('syncA-over')
})
})
return P;
}
function syncB(){
const P = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行syncB');
resolve('syncB-over')
})
})
return P;
}
function syncC(){
const P = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行syncC');
resolve('syncC-over')
})
})
return P;
}
syncA().then((data)=>{
console.log(data);
return syncB();
}).then((data)=>{
console.log(data);
return syncC();
}).then((data)=>{
console.log(data)
})
输出结果为:
这样,每隔两秒输入按顺序输出syncA,syncB,syncC中的内容并执行,传入resolve()的数据在then中也能直接拿到。
Reject的用法
reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。看下面的代码。
//随机生成一个1-10的数字,当数字小于8时调用reject,在then在输出
function syncA(){
const P = new Promise((reslove,reject)=>{
setTimeout(()=>{
let num = Math.floor((Math.random * 10)+1)
if(num>8){
reslove(num)
}else{
reject('小于8')
}
})
})
return P;
}
syncA().then((num)=>{
console.log(num)
},(data)=>{
console.log(data)
})
输出结果为:
Catch的用法
catch方法与then中的第二个参数一样,用来指定reject的回调,也就是上面的代码可以写成:
syncA().then((num)=>{
console.log(num)
})
.catch((data)=>{
console.log(data)
})
catch还有一个重要的作用!!!!当then方法中resolve抛出异常(代码错误)时,也会进入到我们的catch中,将错误信息传入到我们的catch中,代码继续往下执行,并不会中断!与我们的try/catch语句有相同的功能。
all的用法
用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。 有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,是不是很酷?有一个场景是很适合用这个的,一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。
function syncA(){
const P = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行syncA');
resolve('syncA-over')
})
})
return P;
}
function syncB(){
const P = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行syncB');
resolve('syncB-over')
})
})
return P;
}
function syncC(){
const P = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('执行syncC');
resolve('syncC-over')
})
})
return P;
}
Promise
.all([syncA(), syncB(), syncC()])
.then(function(results){
console.log(results);
})
输出的结果为:
Race的用法
race是 【谁跑的快,以谁为准执行回调函数】
//请求某个图片资源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx.jpg';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise.race([requestImg(),timeout()])
.then((results)=>{
console.log(results)
})
.catch((reason)=>{
console.log(reason)
})
requestImg函数会异步请求一张图片,我把地址写为"xxxxxx",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。
补充
8.19:resolve是不接受多个参数的,如resolve(a,b)的时候,b将会被忽略。应改为resolve([a,b])&&sync().then([a,b]),下面是微信群里分享的网易云一面题目以及我的答案
function getValue (a, b) {
const P = new Promise((resolve) => {
setTimeout(() => {
resolve([a, b])
}, 2000)
})
return P
}
getValue(1, 2).then(([a, b]) => {
return a + b
})