一、什么是promise
1、概念
promise是异步编程的一种解决方案,从语法上讲,promise是一个对象,从它可以获取异步操作的信息,从本意上讲,它是承诺,承诺它过一段时间会给你一个结果,promise有三种状态:pending(等待态)、fulfiled(成功态)、rejected(失败态),状态一旦改变,就不会再变,创造promise
1、Promise
是一个构造函数
创建Promise
实例 const p=new Promise
new出来的Promise实例对象,代表应该异步操作
2、Promise.prototype上包含一个.then()
方法
每一次 new Promise() 构造函数得到的实例对象
都可以通过原型链的方式访问到.then()
方法,例如:p.then()
3、.then()
方法用来预先指定成功和失败的回调函数
p.then(成功的回调函数,失败的回调函数)
p.then(result=>{},err=>{})
调用.then()
方法时,成功的函数是必选的,失败的回调函数是可选的
2、特点
(1)、promise
对象的状态不受外界影响
(2)、一旦状态改变,就不会再变,任何时候都可以得到这个结果
3. 状态
Promise对象代表一个异步操作,有三种状态:
pending(进行中): 此时操作尚未完成
fulfilled(resolve)(已成功): 异步操作成功
rejected(reject)(已失败) :异步操作失败
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
4、缺点
(1)无法取消promise
,一旦新建就会立即执行,无法中途取消
(2)如果不设置回调函数,promise
内部抛出的错误,就不会反应到外部
(3)当处于pending
状态时。无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
5、语法
(1)Promise
基本用法
let p=new Promise((resolve,reject)=>{
setTimeout(function(){
let num=Math.ceil(Math.random()*10);
if(num<=5){
//成功时
resolve(num);
}else{
//失败
reject('数字太大了');
}
},2000)
})
p.then((data)=>{
console.log('resolve',data);
},(err)=>{
console.log('reject',err);
})
(2)ajax请求
(3)then方法
如果一个对象实现了then
方法,这个对象被称之为thenable
对象,所有的promise
对象都是thenable
对象,但是并非所有的thenable
对象都是promise
promise
的then
返回值还是一个promise
对象,可以连点使用
then
方法里面的参数为成功后执行,catch
方法里面的参数为失败后执行,Promise
实例生成以后,可以用then
方法分别指定resolve
状态和rejetced
状态的回调函数,也就是说,状态由实例化的参数(函数)执行来决定的,根据不同的状态,看看需要走then
的第一个参数还是第二个参数
resolve()和``reject()
的参数会传递到对应的回调函数的data或err
then
返回的的是一个新的Promise
实例,也就是说可以继续then
let p=new Promise((resolve,reject)=>{
setTimeout(function(){
let num=Math.ceil(Math.random()*10);
if(num<=5){
//成功时
resolve(num);
}else{
//失败
reject('数字太大了');
}
},2000)
})
p.then((data)=>{
console.log('resolve',data);
console.log(somedata);
}).catch((err)=>{
console.log('reject',err);
})
(4)catch()方法
.catch()
方法是.then(null,rejection)
的别名,用于指定发生错误时的回调函数
promise
身上有一个catch
来捕获错误,其实就是then()
方法的第二个参数
(5)链式操作的语法
从表面上看,Promise
只是能够简化层层回调的写法,而实质上,Promise
的精髓是“状态”,用维护状态、传递状态 的方式来使得回调函数能够及时调用,它比传递callback
函数要简单、灵活的多
(6)reslove与reject方法
promise.resolve()
有时需要将现有的对象转为Promise
对象,Promise.resolve
方法就起到这个作用
let jsPromise=Promise.resolve('123'); //将123转为Promise对象
console.log(jsPromise);
Promise.resolve()
方法的参数分成四种情况
1、参数是一个Promise
实例
如果参数是Promise
实例,那么Promise.resolve
将不做任何修改、原封不动的返回这个实例
2、参数是一个thenable
对象
thenable
对象是指具有then
方法的对象,Promise.resolve
方法会将这个对象转为Promise
对象,然后就立即执行thenable
对象的then
方法
let thenable={
then: function(resolve,reject){
resolve(10);
}
}
console.log(thenable);
let p1=Promise.resolve(thenable);
p1.then((res)=>{
console.log('成功',res);
})
3、参数不是具有then
方法的对象,或根本不是对象
如果参数是一个原始值,或是一个不具有then
方法的对象,则Promise.resolve
方法返回一个新的Promise
对象,状态为成功resolved
4、不带有任何参数
Promise.resolve
方法允许调用时不带参数,直接返回一个resolved
状态的 Promise
对象。
所以,如果希望得到一个 Promise
对象,比较方便的方法就是直接调用Promise.resolve
方法。
let p=Promise.resolve();
console.log(p);
p.then((res)=>{ //此时的p就是Promise对象
//....
})
promise.reject()
Promise.reject(reson)
方法也会返回一个新的Promise
实例,该实例的状态为rejected
Promise.reject(reason)
方法也会返回一个新的 Promise 实例,该实例的状态为rejected
//生成了一个Promise对象的实例p,状态为rejected,回调函数会立即执行
let p=Promise.reject('失败');
console.log(p);
p.then(null,(res)=>{
console.log('res',res);
})
//Promise.reject方法的参数是一个thenable对象,执行以后,后面的catch方法的参数res抛出的不是10,而是thenable对象
let thenable={
then: function(resolve,reject){
resolve(10);
}
}
console.log(thenable);
let p1=Promise.reject(thenable);
p1.catch((rej)=>{
console.log('失败',rej);
})
(7)Promise.all()方法
all()
方法的参数都是promise
对象
Promise.all([p1,p2,p3])
:把promise
打包,扔到一个数组里面,打包完还是一个promise
对象,如果是all
方法,必须确保,所有的promise
对象都是resolve
状态,否则就报错
let p1=Promise.resolve('p1成功');
let p2=Promise.resolve('p2成功');
let p3=Promise.resolve('p3成功');
Promise.all([p1,p2,p3]).then(function(res){
//三个成功则成功
console.log('成功',res);
let [res1,res2,res3]=res;
console.log(res1,res2,res3);
},function(err){
//只要有一个失败就全部失败
console.log('失败',err);
})
(8)Promise.race()方法
Promise.race([p1,p2,p3])
:这个和all
方法用法一样,唯一不同之处就是·race·方法只要最前面resolve
就可以正常执行,如果排在前面的是reject
就会报错
let p1=Promise.resolve('p1成功');
let p2=Promise.reject('p2失败');
let p3=Promise.resolve('p3成功');
Promise.race([p1,p2,p3]).then(res=>{
console.log(res);
})
let p1=Promise.reject('p1失败');
let p2=Promise.resolve('p2失败');
let p3=Promise.resolve('p3成功');
Promise.race([p1,p2,p3]).then(res=>{
console.log(res);
})
可以利用race
方法的作用用来判断超时处理
//请求某个图片资源
function requestImg(){
var p=new Promise((resolve,reject)=>{
var img=new Image();
img.onload=function(){
resolve(img);
}
img.src='图片路径';
})
return p;
}
//延时函数,用于请求计时
function timeout(){
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('图片请求超时');
},2000)
})
return p;
}
Promise.race([requestImg(),timeout()]).then((data)=>{
console.log('resolve',data);
}).catch((err)=>{
console.log('reject',err);
})