es6-Promise 学习笔记

171 阅读3分钟

promise 面试必问问题,我项目里又不经常写promise,so 每次问都有些细节不清楚,觉得自己写写,因为阮一峰老师的es6写的很详细了,所以此文章只是笔记

Promise 特性

特点

  1. 三个状态 ,pending(进行中),fulfilled(pending—>resolved),rejected(pending—>rejected)
  2. 当状态改变后,就不会再改变

缺点

  1. 一旦创建就会立即执行,无法取消
  2. 不设置catch回调,Promise内部抛出错误,不会反应到外部。(即js代码继续执行,不会终止)
  3. 当处于pending状态时,无法得知目前进展到哪一阶段

用法

// 对象Promise 接收两个参数且都是函数
// resolve 异步成功时调用
// reject 异步失败时调用

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});


通过then方法指定resolved状态和rejected状态的回调函数。接收的参数是resolve或者reject传来的参数
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

promise.then(value=>{},error=>{});

当resolve返回的是一个Promise

const p1 = new Promise(function (resolve, reject) {
  setTimeout(() => reject(new Error('fail')), 3000)
})

const p2 = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(p1), 1000)
})

p2
  .then(result => console.log(result))
  .catch(error => console.log(error)) // Error: fail

当p2返回的是一个promise对象,这时候,p2的状态由p1决定,then语句针对p1

Promise.prototype.then()

前面说了,then方法接收两个参数,第一个是resolved状态的回调函数,第二个是rejected状态的回调函数

then方法返回的是一个_新的Promise实例_,所以可以采用链式写法。

 <script>      
const p1 = new Promise(function(resolve,reject){ 
       resolve('成功了')     
 })      
const result = p1.then(value=>console.log(value)).then(value=> console.log(value))           
 console.log(result) 
</script>

运行结果

可以看到,真的是返回的promise对象哎,而且链式调用,value最后是undefined

再看一个

     const p1 = new Promise(function(resolve,reject){
          resolve('p1成功了')
     })           
     const p2 = new Promise(function(resolve,reject){  
        resolve('p2成功了')      
      })      
     const res = p1.then(value=>{   
        console.log(value);return p2
      }).then(value=>{ console.log(value);
      },        
      error=>console.log('error',error)) 
           
     console.log(res)

可以想想返回什么

第一个then返回的是一个promise对象p2,之后的第二个then会等待p2的状态发生变化,成功走成功的回调,失败走失败回调

最后的res返回的是新的promise,不是p1也不是p2

Promise.prototype.catch()

catch 用于指定发生错误时的回调函数

p1.then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

这个 等我遇到具体事情的时候再补充吧

说明的一点是,catch可以捕获前面所有then的异常,中间有异常 ,后边的then不会再执行了

 const p1 = new Promise(function(resolve,reject){ 
       resolve('p1成功了')      
})           
const p2 = new Promise(function(resolve,reject){        
       throw new Error('test');      
})      
const res = p1.then(value=>p2).then(
      value=> console.log('value',value)).catch(error=>console.log(error)
)      
console.log(res)
    // Promise
    // Error: test

如果promise内部出现错误,js代码不会停止执行,不会影响到后面代码的执行

Promise.prototype.finally()

一句话,不管promise状态如何,都会执行finally

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

Promise.prototype.all()

用法

const p = Promise.all([p1, p2, p3]);

这个也不难理解,我的理解就是同时执行多个异步,而且返回一个新的Promise对象,只有p1,p2,p3状态全部变为fulfilled时,p才是fulilled,其中一个是rejected,状态就是rejected

需要注意的点

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]

因为p2有自己的catch方法,catch返回新的promise对象,新的promise对象的状态是resolved,所以all方法不会走catch。

Promise.race()

const p = Promise.race([p1, p2, p3]);

这个方法也简单,p1,p2,p3有一个率先改变状态(不管fulfilled还是rejected),p的状态跟着改变,将率先改变的那个promise实例返回

应用

图片懒加载

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();

    image.onload = function() {
      resolve(image);
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}

promise实现ajax请求

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 {
        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);
});