Promise可以理解为一个容器,里面保存了某个未来才会结束的事件(通常是一个异步操作)。
如果我们需要根据这个事件的结果,做响应的后续操作,放在以前,后续操作基本放到了callback里面,要和这个事件紧密耦合在一起。
但是有了promise这个容器,我们就可以把这个事件包装起来,当我们需要做处理的时候,我们再拿到这个proisme容器做相应处理,这样就实现了在代码上的解耦。
1 特点:
1.1 异步操作有三种状态
pending(进行中)、fulfilled(已成功)、 Rejected(已失败)。promise对象状态只根据异步操作结果决定当前状态,其他任何操作都无法改变这个状态。
1.2 一旦状态改变,就保持这个状态,不会再改变。
即使状态已经发生,再对promise对象添加回调函数,也会立即得到这个结果。
2 缺点:
2.1 一旦新建promise,就会立即执行,无发取消
2.2 如果不设置回调函数,promise内部抛出的错误不会反应到外部
2.3 处于pending状态时,无发知道操作进展的阶段
3 promise实例的基本语法:
var promise = new Promise(function(resolve,reject){
// some code 异步操作
if(异步操作成功){
resolve(value) // 改变状态pendding-->resolved,并把结果传递出去
} else {
reject(error) // pendding-->rejected
}
})
promise
.then(function(value){//成功回调}, function(error){ //失败回调})
.then(....)
.catch(function(err){})
3.1 失败回调是可选项
3.2 then()方法指定的回调函数会在脚本同步任务执行完成后,才会执行(mirco task)
new Promise(function(resolve,reject){
console.log(1) // 注意 这个函数里面的代码属于同步代码
resolve()
})
.then(function(){console.log(2)})
console.log(3)
// 打印顺序
1
3
2
3.3 resolve/reject并不会终结Promise的参数函数的执行
new Promise(function(resolve,reject){
resolve() // resolve以后,一般应该在then回到里面进行处理,所以一般 return resolve()
console.log(1)
}).then(function(){console.log(2)})
// 打印
1
2
3.4 假如promiseA里面 resolve(promiseB),一个异步操作的结果是返回另一个异步操作,则promiseB的状态会传给PromiseA(promiseA的状态就有promiseB的状态来决定)
var p1 = new Promise(function(resolve,reject){
setTimeout(()=>{
reject(new Error('fail'))
},3000)
})
var p2 = new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(p1)
},1000)
})
p2
.then(funtion(){
console.log(1)
})
.catch(funtion(err){
console.log(err)
})
// 打印
fail
3.5 then方法返回另一个promise实例,故可以链式调用
then方法回调函数里面return的值,将会作为参数传递给链式中下一个then方法回调函数
p2
.then(funtion(){
return 3
})
.then(function(value){
console.log(value)
})
// 打印
3
如果return 一个promise实例,则then方法返回的promise实例状态,将会被return 的promise实例来决定
参考: 3.4 就会明白
同时要分清楚then返回的promise实例和调用then方法的实例不是同一个,是另外一个,一般链式调用来做连续关联操作,如果不关联,则可以
let p1 = new Promise(function(){...})
p1.then(f1,f2)
xxxxxxxxxxxxxxxxxxxxx其他业务逻辑
p1.then(f3,f4)
对同一个promise实例连续调用then挂载回调,这样也做到了 对扩展开放,对修改封闭这一原则
3.6 catch方法可以捕获promise内部 or then方法抛出的错误
如果没有catch方法,promise内部错误不会传递到外层(在浏览器,不会终止脚本执行,但是会在console打印出来)
catch是then(null,function(err){})的别名
promise对象的错误会“冒泡”,会一直向后传递,直到被catch捕获为止。
catch方法仍然返回一个promise,故可以链式调用
4 Promise构造函数上挂载的方法
4.1 Promise.resolve([data])
返回一个promise实例,且实例fulfilled(已成功)
Promise.resolve(1)
.then((data)=> {console.log(data)})
// 1
4.2 Promise.reject([data])
返回一个promise实例,且实例failed(已失败)
Promise.reject(123)
.then((data)=> {console.log('success'+data)},
(data)=> {console.log('failed'+data)})
// failed123
4.3 Promise.all(arr)
arr元素必须是promise实例。 返回promise实例,且只有数组里面所有的promise都完成,返回的promise才会是fullfiled(已成功)
并且then(arr => {}),返回的数据也是数组
都成功
Promise.all([Promise.resolve(2),Promise.resolve(4),Promise.resolve(8)])
.then((data)=> {
console.log(data[0])
console.log(data[1])
console.log(data[2])
})
// 2
// 4
// 8
有一个失败
Promise.all([Promise.resolve(2),Promise.resolve(4),Promise.reject(8)])
.then((data)=> {
console.log(data[0])
console.log(data[1])
console.log(data[2])
})
// 无任何打印信息
4.3 Promise.race(arr)
arr元素必须是promise实例。 返回promise实例,且只要数组里面某一个promise完成,返回的promise就会是fullfiled(已成功)
并且then(res => {}, err => {}), 返回的是第一个成功/失败的返回的数据
Promise.race([Promise.resolve(2),Promise.resolve(4),Promise.reject(8)])
.then((data)=> {
console.log(data)
})
// 2
Promise.race([Promise.reject(2),Promise.reject(4),Promise.reject(8)])
.catch((data)=> {
console.log(data)
})
// 2
案例:
前端交互操作的封装
https://www.cnblogs.com/whitewolf/p/promise-best-practice.html