什么是异步?
函数传递过去不会立即执行,而是等着请求成功之后才能执行。对于这种传递过去不执行,等出来结果之后再执行的函数,叫做callback,即回调函数.
实现异步的最核心原理,就是将callback作为参数传递给异步执行函数,当有结果返回之后再触发 callback执行
Promise的作用
用回调的方式去实现异步,在多次调用的时候写法将非常复杂,而且影响了后期维护,而promise可以简单解决。
它最大的作用就是解决了异步回调函数层层嵌套的问题
Promise的基本用法
前后台通信ajax模拟,下面是普通的回调实现
let ajax = function (callback) {
console.log('执行');
setTimeout(function () {
callback&&callback.call();//判断回调是否存在
},1000);
};
ajax(function(){
console.log('time1');//一秒以后显示 time1
});
使用promise实现
let ajax = function () {
console.log('执行2');
//resolve执行下一步操作,reject中断操作
return new Promise(function (resolve, reject){
setTimeout(function () {
resolve();
},1000);
});
};
ajax().then(function(){
console.log('time2');//一秒以后显示 time2
},function(){});
使用promise实现连续的链式操作
let ajax = function () {
console.log('执行3');
//resolve执行下一步操作,reject中断操作
return new Promise(function (resolve, reject){
setTimeout(function () {
resolve();
},1000);
});
};
ajax().then(function(){
return new Promise(function(resolve, reject){
setTimeout(function () {
resolve();
},2000);
});
}).then(function(){
console.log('time3');
});
链式操作过程中,如果有一步出错,使用catch捕获错误
let ajax = function (num){
console.log('执行4');
return new Promise(function (resolve, reject){
if(num>5){
resolve();
}else{
throw new Error('错误');
}
});
};
ajax(2).then(function (){
console.log('succcess');
}).catch(function (err){
console.log(err);
});
Promise.all和Promise.race
以加载多张图片为例,了解Promise.all和Promise.race
Promise.all把多个Promise实例当做一个Promise实例,所有图片加载完成以后才会触发Promise.all这个新的对象, 所以Promise.all对象then方法,也就是Promise.all方法返回的是一个Promise实例, 所以才可以调用then方法
function loadImg(src){
return new Promise((resolve, reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload = function (){
resolve(img);
};
img.onerror = function (err) {
reject(err);
};
});
}
function showImgs(imgs){
imgs.forEach(function(img){
document.body.appendChild(img);
});
}
Promise.all([ loadImg('https://ad.12306.cn/res/delivery/0001/2018/03/12/201803121538379477.jpg'), loadImg('https://ad.12306.cn/res/delivery/0002/2018/03/12/201803121543172067.jpg'), loadImg('https://ad.12306.cn/res/delivery/0002/2018/03/12/201803121543172067.jpg')
]).then(showImgs);
Promise.race与Promise.all相反
有一个图加载完就显示到界面,哪个优先返回就先显示哪个,其他忽略不管
function loadImg(src){
return new Promise((resolve, reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload = function (){
resolve(img);
};
img.onerror = function (err) {
reject(err);
};
});
}
function showImgs(img){
let p = document.createElement('p');
p.appendChild(img);
document.body.appendChild(p);
}
Promise.race([
loadImg('https://ad.12306.cn/res/delivery/0001/2018/03/12/201803121538379477.jpg'),
loadImg('https://ad.12306.cn/res/delivery/0002/2018/03/12/201803121543172067.jpg'),
loadImg('https://ad.12306.cn/res/delivery/0002/2018/03/12/201803121543172067.jpg')
]).then(showImgs);