Promise:相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的Promise对象。
特点:
- 用来处理异步操作,它有三个状态:Pending(进行)、Resolved(成功)、Rejected(失败),且它的对象状态不受外界的影响。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。它的状态改变只有两种:一种是Pending到Resolved,另一种是Pending到Rejected。
let pro = new Promise(function (resolved, rejected) {
//执行异步操作
let res = {
code: 201,
data: {
name: 'tom',
age: 18
},
error: '请求失败'
};
setTimeout(() => {
if (res.code === 200) {
resolved(res.data);
} else {
rejected(res.error);
}
}, 1000);
});
console.log(pro);
//then()用来接收当前异步操作完成之后返回的结果
pro.then((val) => {
console.log(val);
}, (err) => {
console.log(err);
})
then()用来接收当前异步操作完成之后返回的结果,第一个参数是Resolved状态的回调函数,第二个参数是可选的,是Rejected状态的回调函数。同时then()返回的还是一个Promise对象的实例,所以可以采用链式编程。
catch(err=>{})是.then(null,err=>{})的别名,用于指定发生错误时的回调函数。通常使用.then(捕获成功).catch(捕获失败)。
如果我们希望setTimeout()的时间由外界传入,我们需要进行简单封装:
function timeOut(ms) {
return new Promise((resolved, rejected) => {
setTimeout(() => {
resolved('请求成功');
}, ms);
});
}
timeOut(2000).then((val) => {
console.log(val);
});
封装ajax
const getJSON = function (url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
//发送
xhr.send();
function handler() {
//console.log(this);
if (this.readyState === 4) {//0表示初始化,1表示还没发送,2、3表示当前进行中,4表示完成
if (this.status === 200) {//200表示成功
resolve(this.response.HeWeather6);
} else {
reject(new Error(this.statusText));
}
}
}
})
};
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976').then((data) => {
console.log(data);
}, (error) => {
console.log(error);
})
Promise的方法
resolve()
resolve:能将现有的任何对象转换成Promise对象
//let p = Promise.resolve('tom');
/*let p = new Promise(function (resolve) {
return resolve('tom');
});*/
let p = new Promise(resolve => resolve('tom'));
console.log(p);//Promise {<resolved>: "tom"}
p.then(data => console.log(data))//tom
reject()
同resolve()
all()
all:多个异步操作并发运行
let pro1 = new Promise((resolve, reject) => {
});
let pro2 = new Promise((resolve, reject) => {
});
let pro3 = new Promise((resolve, reject) => {
});
let pros = Promise.all([pro1, pro2, pro3]);
pros.then(() => {
//3个都成功,才成功
}).catch(err => {
//如果有一个失败,则失败
})
应用: 一些游戏类的素材比较多,等待图片、flash、静态资源文件等都加载完成,才进行页面的初始化。
race()
race:为某个异步请求设置超时时间,并且在超时后执行相应的操作
//1.请求图片资源
function requestImg(imgSrc) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = function () {
resolve(image);
};
image.src = imgSrc;
})
}
//2.超时处理
function timeOut() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('图片请求超时'));
}, 10);
})
}
Promise.race([requestImg('https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3569105906,107357083&fm=26&gp=0.jpg'), timeOut()]).then((data) => {
console.log(data);
document.body.appendChild(data);
}).catch(err => {
console.log(err);
})
注意: race()里面一定是个数组,如果请求成功就不会走timeOut(),直接就走then()。
done()和finally()(了解)
Promise对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为Promise内部的错误不会冒泡到全局)。因此,我们可以提供一个done或finally方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。
作用: 这为在Promise是否成功完成后都需要执行的代码提供了一种方式,避免了同样的语句需要在then()和catch()中各写一次的情况。