ES6-10:Promise

前端开发因为网络交互的存在,产生了一种最常见的独特场景——异步,即程序执行的过程并非完全按照代码的书写顺序执行。异步编程的解决方法有①回调函数、②事件、③Promise、④观察者对象;
Promise是ES6提供的一种异步编程的一种解决方案。简单来书就是一个容器,里面存放着某个未来才会结束的事件;从语法角度来说是一个构造函数(对象),可以对各种异步操作进行同样的处理方法。

1.Promise特点

  • 3种状态:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败);
  • 对象状态不受外界影响:只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态;
  • 2种不可逆状态改变:只有两种状态改变①Pending->Fulffiled、②Pending->Rejected;只要两种情况发生任何一种,状态就凝固定型不再改变,即Resolved,任何时候都能且仅能得到这个结果;即使在添加新的对象也立即得到Resolved的结果;

2. 创建方法

  • 创建:let p=new Promise(function(resolved,reject){});
var promise=new Promise(function(resolve,rejecte){
//do somthing here
if(/*异步操作成功*/){resolve(value)
}else{reject(value)};
})

// 案例1 :Promise创建时立即执行
let promise1=new Promise(function(resolve,reject){
    console.log("Promise is creating...");
    resolve();
});
promise1.then(function(){console.log("Promise is resolved !")});
console.log("Hi Script is Running...");


// Promise is creating...
// Hi Script is Running...
// Promise is resolved !

// 案例2:Promise返回值可带参数
var p1=new Promise(function(resolve,reject){});
var p2=new Promise(function(resolve,reject){
    // do some other things...
    resolve(p1);
})

// 案例3 :Promise状态定型的会回调函数在本轮事件循环结束时执行
new Promise((resolve,reject)=>{
    console.log(1);
    resolve(2);
    console.log(3);
}).then(res=>{
    console.log(res);
})
// 1
// 3
// 2

// 案例4:显示return语句后的代码不执行
new Promise(function(resolve,reject){
    console.log(1);
    return resolve(2);
    console.log(3);
}).then(res=>{
    console.log(res)
});
console.log(4)
// 1
// 4
// 2

Promise构造函数接受一个函数作为参数,参数函数提供两个参数方法,分别是resolve和reject,这两个方法有JavaScript引擎提供,不用自己部署;Promise实例创建后会立即执行,然后会执行代码中所有的同步操作, 最后会在Promise状态定型后,执行then方法指定的回调函数 ;Promise的回调函数resolve和reject都可带有参数;Promise的回调函数在状态定性后的下一轮事件中执行,即无论状态在何处定型(resolve()),都不影响Promise中其他代码的执行,但显示return语句会影响;

3. 基本方法

  • Promise.prototype.then(resolveFn,rejectFn?):为Promise实例添加状态改变是的回调函数,返回至为Promise对象;该方法可链式重复调用,将前一个处理结果作为下一个函数的入参,如: promise.then().then()
  • Promise.prototype.catch():指定Promise发生错误时的回调函数,返回值为Promise对象,即Promise.then(null,rejection)的别名;Promise的错误对象具有“冒泡”性质,会一直向后传递,直到被catch或reject捕获;但如果Promise没有使用catch指定错误的处理方法,Promise的错误方法将永远不会传递到外层代码,即不会有任何反应;
// 案例5:Promise 错误对象冒泡--then过程中的错误会一直传递给最后至被捕获
let p1=new Promise((resolve,reject)=>{resolve(httpFn)});
let p2=new Promise((resolve,reject)=>{p1});
let p3=new Promise((resolve,reject)=>{});
p3.then(p2).then(otherFn).catch(err=>{errorFn});

// 案例6:Promise的状态一旦定性将无法被改变,即一个Promise实例有且仅有一次改变状态的机会
let p4=new Promise((resolve,reject)=>{
    resolve('ok');
    throw new Error('test');
});
p4.then(res=>{console.log(res)}).catch(err=>{console.log(err)});
// ok

// 案例7
let soneFn=function(){
    return new Promise(function(resolve,reject){
        resolve(x+2);//此处应该报错,因为x未声名 
    })
}
someFn.then(function(){console.log('Everythings is ok.')});
// Everything is ok.
/////因未使用catch捕获Promise异常,报错不会被捕获,也不会传递到外层代码;相反代码正常运行,但会打印错误ReferenceError: x is not defined.

  • Promise.all(arrLike):将一个具有Iterator接口的数据对象包装成一个新的Promise实例,返回值;

①参数arrLike可以是Promise数组、或具有遍历器的数据;如果参数不是Promise数组,则调用Promise.resolve()方法将参数转为Promise实例,在进一步处理;

②返回Promise实例的状态:被封装的Promise实例都为Fullfiled状态时,封装返回Promise状态才会变成Fullfied;否则只要有一个为rejected,则会将第一个rejected的实例返回给封装后的Promise,同时,封装后的Promise都会变成rejected;

let pro1=new Promise.all([p1,p2,p3]);
let pro2=new Promise.all([1,2,3]); 
  • Promise.race(arrLike):将多个具有Iterator接口的数据包装成一个Promise实例;与Promise.all()方法类似;不同之处在于,只要被包装的Promise实例只要有一个率先改变状态,变回将状态结果传递给封装后的Promise对象;
  • Promise.resolve(argu):将一个数据转换成Promise对象;根据传入参数类型的不同处理方法不同,如下:
    ① 参数不存在:直接返回一个状态为Resolved的Promise对象;
    ② Promise对象:返回Promise对象,不做任何处理;
    thenable对象:即一个具有then方法的对象;将这个对象转换成Promise对象并立即执行htneable的then方法;
    ④ 不具有thenable方法或非对象:返回一个新的Promise对象,状态为resolved,结果为参数本身;
  • Promise.reject(argu):返回一个Promise对象,其状态为Rejected;错误结果为整个参数本身;

5. 与steam事件、Observerble(观察者模式的区别)

  • Promise、Observe都是将异步操作转换成同步操作的实现方式;
  • Promise、Observe都可以进行聚合操作;
  • Promise的状态是不可逆 的,其状态仅有一次改变的机会,一旦改变,状态便定型;结果值需要手动调用才可传递给后续操作
  • Observe的状态是可以多次重复可变的,其状态会根据入参改变并传递给观察者;结果值会主动通知到所有订阅者(后续操作);
原文地址:https://www.cnblogs.com/hbzyin/p/8012315.html