new Promise( function(resolve, reject) {...} /* executor */ );
复制代码
executor
是带有 resolve
和 reject
两个参数的函数 。Promise构造函数执行时当即调用executor
函数, resolve
和 reject
两个函数做为参数传递给executor
(executor 函数在Promise构造函数返回新建对象前被调用)。resolve
和 reject
函数被调用时,分别将promise的状态改成_fulfilled(完成)或rejected(失败)。executor 内部一般会执行一些异步操做,一旦完成,能够调用resolve函数来将promise状态改为_fulfilled,或者在发生错误时将它的状态改成rejected。若是在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
一个 Promise
有如下几种状态:javascript
pending: 初始状态,既不是成功,也不是失败状态。html
fulfilled: 意味着操做成功完成。java
rejected: 意味着操做失败。ajax
let status = 1;
// 判断status是否为1,是1的时候执行成功
let p1 = new Promise(function(resolve,reject){
if(status==1){
resolve({msg:"执行成功",status:"200"}); // 这里传递给resolve的数据就是以后then中接受到的res
}else{
reject({msg:"执行失败",status:"404"}); // 对应catch中的err
}
});
p1.then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
复制代码
promise能够当作是去肯德基买汉堡,先预约一个汉堡,而后收营员会给你一小票并向你承诺以后会给你一个汉堡(也可能汉堡买完了没有汉堡)。从下单到得到汉堡的这个过程能够当作是异步的操做,期间你能够刷一下子手机,同时后厨在准备汉堡。有了汉堡以后吃汉堡(处理resolve),或者没有汉堡了发生退款(处理reject)。
你在等待这个承诺的到来,一旦到来你就能够开始吃汉堡或者没有汉堡遗憾的退款。数组
then
并非处理promise
实例返回的resolve
状态值,resolve
和reject
状态的值都可以处理,第一个回调函数处理成功,第二个回调函数处理失败,若是缺省第二个处理失败的回调,则状态为reject
的promise
传递到下一个链式调用。 promise
只有两种变化过程,并且变化以后以后不会发生变化,会保持状态的一致
只能从 _pending -> fulfilled 或者 从 pending -> rejected _一旦状态发生变化就不会再发生改变,保持一致性。(你去买汉堡只可能有两种状态,买到汉堡和没有买到,并且不可能在二者之间变化)异步
var promise = new Promise((resolve, reject) => {
// 只能改变一次状态
resolve('1') // 改变状态
resolve('2') // 不生效
resolve('3') // 不生效
console.log('4') //同步执行
})
// 屡次调用promise中的值不会发生变化
promise.then((data) => {
console.log('第一个then', data)
})
promise.then((data) => {
console.log('第二个then', data)
})
// 4
// 第一个then 1
// 第二个then 1
复制代码
promise
能够链式调用不是由于使用return this
, 而是在then
和 catch
以后返回了一个promise
then
或者catch
返回当即值,则返回的promise
是resolved
状态,至关于Promise.resolve(..)
Promise.reject(..)
,则返回的promise
是rejected
状态var promise = new Promise((resolve, reject) => {
resolve('1')
})
promise.then((data) => {
console.log(data) // 1
return 2 // 做为新的promise的resolve值返回
}).then((data) => {
// 这里接收的是上一个then返回的新的promise的resolve状态
console.log(data) // 2
})
promise.then((data) => {
// 能够返回一个promise
return Promise.reject('错误')
}).catch((data) => {
// catch接收上一个then返回的promise
console.log(data) // 错误, 接收上一个链上的promise的resolve返回
}).then((data) => {
console.log(data) // undefined 前一个链上的promise没有返回值
})
promise.then((data)=>{
// 抛出错误
throw new Error('出错')
}).catch((err) => {
// 上一个promise返回的是reject, 内容是 抛出的error
console.log(err)
})
// 1
// 2
// Error: 出错
// at promise.then (3.html:32)
// 错误
// undefined
复制代码
return new Error('错误')
的方式返回异常不能被下一个catch
捕获到,这里返回的promise
是resolve
状态,会被传递下去被then
捕获,只有throw new Error()
才能被下一个catch
捕获var promise = new Promise((resolve, reject) => {
resolve('1')
})
promise.then((data) => {
return new Error('错误')
}).catch((err) => {
console.log('不会执行')
}).then((data) => {
console.log('打印以前返回的错误', data)
})
// 打印以前返回的错误 Error: 错误
// at promise.then (4.html:16)
复制代码
then(success, error)
then
能够由两个处理函数,第一个用来处理resolved
状态的promise
返回值,第二个用来处理rejected
状态的promise
返回值,这里处理的是链式调用的返回的前一个promise
var promise = new Promise((resolve, reject) => {
reject('错误')
})
promise.then((data)=>{
console.log('不会执行,promise状态是rejected')
}, (err)=>{
// 捕获到错误
console.log(err) // 错误
}).catch((err) => {
// 链式调用的前一个promise返回是一个resolve状态
console.log('不能捕获到错误')
})
复制代码
then
中没有指定处理rejected
状态的函数时,错误状态会一直传递下去直到被处理,要是没有处理不会被window
捕获,直接控制台报错...window.addEventListener('error', (e) => {
console.log(e)
})
var promise = new Promise((resolve, reject) => {
reject('错误')
})
promise.then((data)=>{
console.log('未对错误处理')
}).catch((err) => {
// 执行
console.log('上一个then中缺省处理错误的函数,错误会被封装成新的promise向下传递', err)
})
promise.then((data)=>{
console.log('不处理,也没有后续,错误会被window捕捉到')
})
复制代码
.then
的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,然后续的 .catch
能够捕获以前的错误var promise = new Promise((resolve, rejected) => {
resolve(1)
})
promise.then((data)=>{
throw new Error('2')
}, (err) => {
console.log('不能捕获,then中第一个成功回调返回的错误')
}).catch((err)=>{
console.log('能够捕获上一个then中成功或者错误处理函数中抛出的错误')
})
复制代码
// 传入当即数
Promise.resolve(1).then((data)=>{console.log(data)}) // 1
// 传入promise对象
var p1 = new Promise((resolve,reject) => {
resolve(2)
})
var p2 = Promise.resolve(p1)
console.log(p1 === p2) // true 返回同一个
// thenable
var o = {
then:function(cb,err){
console.log('then函数')
cb(3)
}
}
Promise.resolve(o).then((data)=>{console.log(data)}) // then函数 3
复制代码
判断一个函数是否是thenable函数
if(!!p
&&
(typeof p === 'object' || typeof p === 'function')
&&
(p.then && typeof p.then === 'function')
) { console.log(true)} else {
console.log('false)
}
复制代码
Promise.all
方法常被用于处理多个promise
对象的状态集合。输入是一个由promise
对象组成的数组,全部的promise对象都成功的时候才会触发成功,一旦有任何一个iterable
里面的promise
对象失败则当即触发该promise
对象的失败。这个新的promise
对象在触发成功状态之后,会把一个包含iterable
里全部promise
返回值的数组做为成功回调的返回值,顺序跟iterable
的顺序保持一致;若是这个新的promise
对象触发了失败状态,它会把iterable
里第一个触发失败的promise
对象的错误信息做为它的失败错误信息。ui
这时候能够这样,将一组ajax请求封装成一组promise
对象传入Promise.all
,返回结果也是有序的,再对这个有序的promise
对象进行处理this
Promise.race
当iterable
参数里的任意一个子promise
被成功或失败后,父promise
立刻也会用子promise
的成功返回值或失败详情做为参数调用父promise
绑定的相应句柄,并返回该promise
对象。(任意一个成功或者失败就触发)
此时能够构造一个 定时器任务和一个ajax
请求,封装成promise
对象传入Promise.race
,若是定时器的结果先返回,则请求超时