Promise 异步编程的一种解决方案

142 阅读4分钟

1. 简介

promise(承诺),异步编程的一种解决方案,比传统的解决方案,回调函数和事件——更合理和更强大。
promise 一种容器,里面保存着某个未来才会结束的事件(通常是一个异步操作),就像它的中文一样(承诺),许下的承诺;

  1. 状态

    promise 有三种状态:pending(进行时),fulfilled(已成功),rejected(已失败)。
erDiagram
Promise ||--o{ fulfilled : pending
Promise }|..|{ rejected : pending
  1. 特点

对象的状态不受外界的影响;

promise对象代表的是一个异步操作;它的三种状态不受外界的影响,只有异步操作的结果,可以决定当前是哪一种状态;任何其他操作都无法改变。

一旦状态改变,就不会再变,任何时候都可以得到这个结果。

Promise一旦执行,无论结果如何,都会被记住。任何时候提起都是(resolved)已定型的;从pending变为fulfilledpending变为rejected.如果改变已经发生,再用回调函数获取Promise这个状态,是可以获取到的;这个和事件(event)不同,事件(event)一旦你错过了它,想要监听得到结果,是不可能的。 缺点:

  • Promise 一旦执行,无法取消;
  • 如果没有设置回调函数,Promise内部抛出的错误,不能反映到外部;
  • 当处于pending状态时,无法知道当前是处于什么状态,(刚开始,还是快结束。)

2. 基本用法

声明一个 Promise 实例

 // Promise 实例接收两个参数 resolve,reject
   var Promise = new Promise( function ( resolve,reject ) {
	if ( /* 异步操作成功的判断 *) {
		// value成功接收的参数
		resolve(value);
	} else {
		// value失败接收的参数
		reject(value);
	};
   })

Promise构造函数接受一个函数作为参数,这个函数接受resolverejected作为参数。它们是两个函数,由Javascript引擎提供。

  • resolve的作用,是将Promise对象的状态从“pending”变为“resolve”,在异步成功时调用,并将异步操作的结构,作为参数传递出去;
  • rejected 的作用,是将promise对象的状态从“pending”变为“rejected”,在异步失败时,将异步操作的结果,作为参数传递出去;

调用
Promise 生成example以后,可以用then方法分别指定resolverejected状态的回调函数;这两个函数都是可选的,不一定要提供;

 
Promise.then( ( value ) => {
    // resolve的回调函数
},( error ) => {
    // rejected的回调函数
})

注意:调用 resolvereject 并不会终结 Promise 的参数函数的执行。

new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})
  • 创建一个 ajax case,后面要做引用
 const getJSON = function(url) {
    const promise = new Promise(function(resolve, reject){
      const handler = function() {
        if (this.readyState !== 4) {
          return;
        }
        if (this.status === 200) {
          resolve(this.response);
        } else {
            console.log();
          reject(new Error(this.statusText   ));
        }
      };
      const client = new XMLHttpRequest();
      client.open("GET", url);
      client.onreadystatechange = handler;
      client.responseType = "json";
      client.setRequestHeader("Accept", "application/json");
      client.send();

    });

    return promise;
  };

  getJSON("/posts.json").then(function(json) {
    console.log('Contents: ' + json);
  }, function(error) {
    console.error('出错了', error);
  });

3. Promise.prototype.then()

Promise实例具有then方法,then方法是定义在原型对象Promise.prototype上的,作用是为promise实例添加状态改变时的回调函数;
then方法返回的是一个新的Promise实例函数;可以采用链式写法,then方法后面再跟一个then方法。

getJSON('/posts.json').then( (json) => {
    return json.post;
}).then( ( post) => {})

4.Promise.prototype.catch()

Promise.prototype.catch()方法是.then(null,rejection).then(undifined,rejection)的别名,在发生错误时的回调函数;resolve失败时的回调,或者接口函数调用失败时的回调函数;

// Promise.prototype.catch()的使用
getJSON('/post.json').then( (posts) => {
    //成功时的处理函数
}).catch( ( error ) =>{
    //处理 getJson 和前一个回调函数失败时的发生的错误
    console.log(error);
})
  • 使用.then 链式写法处理错误
p.then( (val) => console.log('fulfilled:',val))
.catch( ( err ) => console.log('rejected:',err));
// 等同于 
p.then( ( val ) => console.log('fulfilled:',val))
.then( null,( err ) => console.log('rejected:'.err));

前面有说过,.then()返回的是一个promise()函数,所有.then()链式写法可以处理上一个.then()方法返回的Promise回调函数事件;

  • case
var Promse1 = new Promise( ( resolve,reject) => {
// 抛出一个错误
throw new Error('test')
});

// 监听
Promse1.catch( ( error ) => {
    console.log(error);  
})


// Error:test
  • 使用try catch 结合 rejecte 抛出错误
var promise2 = new Promise( ( resolve,reject ) => {
    try {
        console.log('caught error');
        throw new Error('test1')
    } catch( e ) {
        // 使用rejecte接收 e 错误,并作为参数抛出
        reject(e);
    };
});
 // 监听
promise2.catch( ( error ) => {
    console.log(error);
})
  • 使用 reject 捕获错误 并当参数抛出
var promise3 = new Promise( ( resolve,reject ) => {
    reject( new Error('test3'));
});

// 监听
promise3.catch( ( error ) => {
    console.log('%c 使用reject抛出的错误:' + error,'color:red');
});

// 使用reject抛出的错误:Error: test3
  • 当 promise 状态已经变成 resolve 时,再抛出错误是不能捕获的,因为当 promise 状态一旦改变就永远保持不变。(承诺的结果一旦失败或成功,留给后人的永远只有一个结果。)
var promise4 = new Promise( ( resolve,reject ) => {
        resolve(' status is ok ');
        throw new Error('test4');
});

promise4.then( ( resolve ) => console.log(resolve))
.catch( ( error ) => console.log(error));
//  status is ok 
  • 冒泡 promise 对象的错误有“冒泡”性质,会一直向后传递,直到被最后一个catch()方法捕获;
getJSON('/post/1.json').then(function(post) {
    return getJSON(post.commentURL);
}).then(function(comments) {
    // some code
}).catch(function(error) {
    // 处理前面三个Promise产生的错误
    console.log(error);

});

上面的代码中有三个promise对象产生,一个由getJSON()函数,还有两个then()方法产生

Loading~~~