1:
下面的例子,promise指定在下一轮‘事件循环’再抛出错误;到了那个的时候,promise的运行已经结束,所以这个错误实在promise函数体外抛出来的;会冒泡到最外层;成为了没有捕获的错误;
var promise=new Promise(function (resolve,reject) {
resolve('OK')
setTimeout(function () {
throw new Error('TEST1')
},0)
setTimeout(function () {
throw new Error('TEST12')
},2000)
})
promise.then(function (value) {
console.log(value)
})
运行结果如下:
webstrom环境错误如下:
google环境下的错误如下
2:
node的unhandledRejection事件;专门监听没有捕获的reject错误;经过测试,发现在3个环境中都没有捕获到;
process.on('unhandledRejection', function (err, p) {
console.log(err)
})
3:如果promise状态已经变为resolved,再抛出错误也是无效的,并不会被捕获,等于没有输出;注意跟上面的定时器抛出错误的区别;
var promise = new Promise(function (resolve, reject) {
resolve('OK');
console.log('haohao')
throw new Error('TEST1')
})
promise.then(function (value) {
console.log(value)
}).catch(function (error) {
console.log(error)
})
4:then()方法返回的是一个新的promise实例(注意不是原来的那个promise实例);因此可以采用链式写法:then后面可以再次调用另外一个then方法
5:catch()方法是then(null, rejection)的别名,用于指定发生错误时的回调函数;因此返回的也是一个promise对象;
getJSON('/post.json').then(function () {
//如果promise对象状态变为resolved,则会调用then方法指定的回调函数
}).catch(function () {
//如果promise对象状态变为rejected,会调用catch方法指定的回调函数;另外then方法指定的回调函数如果在运行中抛出错误,也会被catch捕获;
})
因此不要在then方法定义rejected状态的回调函数(then的第二个参数),应该总是使用catch方法;
6:写上catch跟不写catch的区别如下:貌似也没啥区别,都不会影响后面代码的执行;退出码是0表示执行成功;
(1)
var someAsyncThing=function () {
return new Promise(function (resolve,reject) {
resolve (x+2)
})
}
someAsyncThing().then(function () {
console.log('everything is good')
})
console.log('haohao')
(2)
var someAsyncThing=function () {
return new Promise(function (resolve,reject) {
resolve (x+2)
})
}
someAsyncThing().then(function () {
console.log('everything is good')
}).catch(function (error) {
console.log(error)
})
console.log('haohao')
(3)
var someAsyncThing=function () {
return new Promise(function (resolve,reject) {
resolve (x+2)
})
}
someAsyncThing().catch(function (error) {
console.log(error)
}).then(function (value) {
console.log(value)
})
(4)没有报错的话,会跳过catch方法,直接执行后面的then方法;
Promise.resolve().catch(function (error) {
console.log(error)
}).then(function () {
console.log('carry on')
})
7:Promise.all()用于将多个Promise实例包装成一个新的Promise.allPromise实例;
var promises=[2,3,5,7,11,13].map(function (id) {
return getJSON('/post/'+id+".json")
})
Promise.all(promises).then(function (posts) {
}).catch(function () {
})
(1)map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
(2)只有6个实例的状态都变成fulfiled,或者其中一个变为rejected,才会调用Promise.all后面的回调函数;
8:Promise.race()
参数:接受一个数组,数组内都是Promise实例
返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例率先处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例率先处于reject状态,返回的Promise实例变为reject状态。
9:Promise..resolve():用户将现有对象转为Promise对象,
(1)如果参数是Promise实例:原封不动返回
(2)如果参数是enable对象(具有then方法的对象),Promise..resolve()会将这个对象转为promise对象,然后立即执行thenable对象的then方法
let thenable={
then:function (resolve, reject) {
resolve(42)
}
}
let p1=Promise.resolve(thenable)
console.log(p1) //Promise { <pending> }
p1.then(function (value) {
console.log(value) //42
})
(3)参数是一个原始值,或者是一个不具备then方法的对象,或者根本不是对象;那么该方法返回一个新的promise对象,状态为resolved;
var p=Promise.resolve('hello')
console.log(p) //Promise { 'hello' }
p.then(function (s) {
console.log(s) //hello
})
上面的代码生成一个新的promise对象的实例p,由于字符串‘hello’不属于异步操作(判断方法是字符串对象不具有then方法),返回promise实例的状态从生成起就是resolved(已定型);所以回调函数会立即执行;Promise.resolve(‘hello’)的参数会同时传递给回调 函数;
(4)不带有任何参数:
Promise.resolve()的promise对象是在本轮‘事件循环’结束时,而不是在下轮事件循环开始时
var p=Promise.resolve()
console.log(p) //Promise { undefined }
p.then(function (s) {
console.log(s) //undefined
})
setTimeout(function () {
console.log(three)
})
Promise.resolve().then(function () {
console.log('two')
})
console.log('one')
//one
//two
//three
10:promise.reject()方法
这个方法的参数会原封不动的作为reject的理由,变成后续方法的参数;
var p=Promise.reject('出错了')
p.then(null,function (s) {
console.log(s) //出错了
})
var p1=new Promise((resolve, reject)=> reject('出错了'))
p1.then(null,function (s) {
console.log(s) //出错了
})
以下的方法不在ES6中,
1:done():总是处于回调链的尾端,保证抛出任何可能出现的错误;(无论promise对象的回调以then方法还是catch结尾,只要最后一个方法抛出错误,都有可能无法捕捉;)done()方法可以像then一样使用,提供fullfilled , rejected状态的回调函数,也可以不提供任何参数,不管怎么样,done方法都会捕捉到任何可能出现的错误;
实现方式如下:
Promise.prototype.done=function (onFulfiled, onRejected) {
this.then(onFulfiled, onRejected).catch(function (reason) {
setTimeout(()=>{ throw reason},0)
})
}
2:finally()用于指定不管promise对象最后状态如何都会执行的操作;跟done最大的区别就是:它接受一个普通回调函数作为参数,该函数不管怎么样,都会执行;
Promise.prototype.finally=function (callback) {
let P=this.constructor
return this.then(
value => P.resolve(callback()).then(()=>value),
reason => P.resolve(callback().then(()=>{ throw reason}))
)
}
3:实际开发中经常碰到一种情况:不知道或者不想区分函数f是同步还是异步操作。但是想用promise处理它,因为这样就可以不管f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理抛出的错误;
const f=()=>console.log('now')
Promise.resolve().then(f)
console.log('next')
//输出结果
//next
//now
上面的代码函数f是同步的,但是用promise包装以后就变成异步执行了;暂时先不研究
(1)第一种解决办法: