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)// 打印顺序132
3.3 resolve/reject并不会终结Promise的参数函数的执行
new Promise(function(resolve,reject){resolve() // resolve以后,一般应该在then回到里面进行处理,所以一般 return resolve()console.log(1)}).then(function(){console.log(2)})// 打印12
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
