1.Promise(解决异步操作问题的)
- 什么是异步
比如:函数a,执行一个步骤,a执行完要执行b;有一个顺序问题;
在程序上设置a执行完执行b,一种通过回调方式,一种通过事件触发方式; - Promise的作用
- Promise的基本用法
2.模拟ajax的过程
{
//ES5中回调解决异步操作的问题;
//前端和服务端通信有一个ajax的过程;
let ajax =function(callback){
console.log('执行');
setTimeout(function(){
//判断这个回调是不是存在,如果存在就执行下一步;
callback && callback.call();
},1000);
};
//使用:调用这个方法,传一个回调函数;
ajax(function(){
console.log('timeout1');
});
//输出结果:先输出了 执行(这个是ajax这个函数这个步骤执行的)
一秒钟之后执行了回调函数,输出了 timeout1;
}
3.Promise--then方法
- 如果这个过程变的复杂,先执行a在执行b,b完了之后在执行c,以此类推,用回调的方式去处理,这个代码写法将非常复杂;
- 这个代码的复杂影响了后期的维护;很难一眼看出来这个回调的顺序问题,到底哪个在前哪个在后;
{
let ajax = function(){
console.log('执行2');
//ajax这个函数运行完之后,返回一个对象,Promise实例,这个实例有了一个then方法,
就执行下一步的功能;
//怎么去执行呢?这里面有两个参数resolve,reject;
//resolve:要执行下一步操作;reject:要中断当前的操作;
return new Promise(function(resolve,reject){
setTimeout(function(){
//一秒钟之后执行下一步的步骤;
resolve();
},1000);
});
};
//then这个参数这个函数体就是要执行的下一步;
/*
* ajax().then(function(){
* //第一个function对应的resolve;
* console.log('Promise','timeout2');
* },function(){
* //第二个function对应的是reject;
* });
*/
ajax().then(function(){
//第一个function对应的resolve;
console.log('Promise','timeout2');
});
//输出结果:执行2 Promise timeout2
}
4.多步回调:
{
let ajax =function(){
console.log('执行3');
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('timeout3');
});
//执行3 timeout3
}
5.串行过程 a b c 在中间某一步出错,怎么捕获这个错误
- Promise提供了一个catch方法,捕获异常错误;
{
let ajax = function(num){
console.log('执行4');
return new Promise(function(resolve,reject){
if(num>5){
resolve();
}else{
throw new Error('出错了');
}
);
};
ajax(6).then(function(){
console.log('log',6);
}).catch(function(err){
console.log('catch',err);
});
//log 6
ajax(3).then(function(){
console.log('log',3);
}).catch(function(err){
console.log('catch',err);
});
//catch Error:出错了
}
6.Promise.all 和Promise.race
eg:1.所有图片加载完在添加到页面
{
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:把多个Proimse实例当做一个Promise实例;
//all下面一个数组,数组传递进来多个Promise实例;当所有promise实例状态发生改变的时候;
新的Promise实例才会跟着发生变化;
(下面这三张图片的状态都完成之后,才会触发Promise.all这个新的Promise对象,所以这个
Promise对象才会有then方法;
Promise.all方法返回的是一个Promise实例,所以才可以调用then方法;
--loadImg本身是一个Promise实例,这个promise实例是做一个图片加载的动作,把三个图片加载
的动作放在Primose.all这个函数里面,生成一个新的promise实例,当三张图片都加载完之后,
才会触发显示图片的逻辑;
Promise.all([
loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs);
}
eg:2:场景:三张图片位于三个不同的位置,页面需要加载一张图片,三张图片不知道哪张返回的比较快;
- 三张图片有三个来源,加载出来一个就可以;(先到先得)
{
//有一个图片加载完就添加到页面上;
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);
}
//多个实例中,有一个状态先改变,最后这个race实例也会跟着改变,其他的就不在响应了;
Promise.race([
loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs);
//只显示了一个;
}