Promise详解

什么是promise

ES6异步编程的一种解决方案,将异步操作以同步的方式表达出来,避免层层嵌套的回调函数

为什么要用promise

  1. 指定回调函数的方式更加灵活
  • 使用纯回调函数方式,必须在异步任务执行前指定回调函数
// 成功的回调函数
function successCallback(result) {
  console.log("音频文件创建成功: " + result);
}

// 失败的回调函数
function failureCallback(error) {
  console.log("音频文件创建失败: " + error);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback)
  • promise 可以在启动异步任务后指定回调函数,甚至可以在异步任务结束后绑定回调函数
const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);

setTimeout(() => {
  promise.then(successCallback, failureCallback);
 },2000)
  1. 支持链式调用,解决回调地狱
    回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果,是嵌套的回调函数执行的条件
    嵌套的回调函数不便于阅读、不便于异常处理
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

Promise 链式调用

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

promise链式调用异常传递

new Promise((resolve,reject) => {
  reject(1)
}).then(
  value => {
    console.log('onResolved',value)
    return 2
  },
  // error => { throw error } 
  // error => Promise.reject(error) 
).then(
  value => {
    console.log('onResolved',value)
    return 3
  },
  // error => { throw error } 
).catch(reason => {
  console.log('onRejected',reason)
})
输出:onReject 1

一遇到异常抛出,浏览器就会顺着 Promise 链寻找下一个 onRejected 失败回调函数或者由 .catch() 指定的回调函数,相当于注释代码的两种写法之一

中断promise链

new Promise((resolve, reject) => {
    reject(1);
})
.then(() => {
    console.log(2);
})
.catch(() => {
    console.log(3);
    //要中断catch()后面的then()方法,
  return new Promise(() => {}); //返回一个padding的promise
})
.then(() => {
    console.log(3);
});

promise的特点

  • 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、resolved(已成功)和rejected(已失败)

  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved和从pending变为rejected

  • promise内部发生错误,不会影响到外部程序的执行。

  • 无法取消Promise。一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

用法

创造promise 实例时,必须传入一个函数作为参数

new promise(() => {});

该函数可以接收另外两个由JavaScript引擎提供的函数,resolve和reject。函数作用:

  • resolve——将Promise对象的状态从pending变为resolved,将异步操作的结果,作为参数传递出去
  • reject——将Promise对象的状态从pending变为rejected,将异步操作报出的错误,作为参数传递出去
let promise = new promise((resolve, reject) => {
  //do something
  if(true){
    //将参数返回,供then方法使用
    resolve('value');
  }else {
    reject('error');
  }
});

promise 实例方法

promise.prototype.then()

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。then方法返回的是一个新的Promise实例

promise.then(
  //resolved时调用,value为resolve函数返回的参数
  value => {
    console.log(value);
  },
  err => {
    //reject时调用
    console.log(err);
  }
 );

当then方法只有一个函数参数时,此时为resolved状态的回调方法

 promise .then(value => {
    console.log(value);
  })
  .catch(err => {
    //
}
`推荐这种方式,可以捕获前面then方法执行中的错误

Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名
Promise 新建后就会立即执行,并且调用resolve或reject后不会终结 Promise的参数函数的执行。

let promise = new Promise(function(resolve){
   console.log('promise');
   resolve();
   console.log(1)
})
promise.then(function() {
   console.log('resolved');
})
console.log(2)
//promise
//1
//2
//resolved

Promise.then()返回的promise状态是什么?

由then()指定的回调函数的执行结果决定
1、如果抛出异常,返回的promise变为rejected,error为抛出的异常
2、如果返回非promise的任意值,返回的promise变为resolved状态,value为返回的值
3、如果返回另一个新的promise,此promise的结果就是返回的promise的结果

const p = new Promise(function(resolve,rejected){
  resolve(1)
})
p.then(value => {
  //情况1:抛出异常
  throw '错误'

  //2.返回一个值
  return value+1;

  //3.返回一个Promise
  return new Promise((resolve, reject) => {
    resolve(value+2)
  });
  return new Promise((resolve, reject) => {
    reject(value+3)
  });

  //4.没有返回值
  相当于 return undefined

}).then(value => {
  console.log('onResolved',value);
},error => {
  console.log('onRejected',error)
});
  1. 抛出的异常将作为then方法返回的promise的reject的值传递出
    输出: onRejected 错误
  1. return的值将作为then方法返回的promise的resolve的值传递出
    输出: onResolved 2
  1. return 的promise的结果将作为then方法返回的promise的结果
    分别输出: onResolved 3 ,onRejected 4
  1. 构造then方法的函数没有向then方法返回的promise对象的resolve方法传递值。因此resolve返回的是undefined
    输出: onResolved undefined
  • promise.catch()
  • promise.finally() 无论成功失败都执行

静态api方法

promise.all() 将多个 Promise 实例,包装成一个新的 Promise 实例

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

p1,p2,p3都是Promise实例;p的状态由p1、p2、p3决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

promise.race()方法是将多个Promise实例包装为一个实例

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

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Promise.resolve()
Promise.resolve(1)
// 等价于
new Promise(resolve => resolve(1))

Promise.resolve()方法的参数:

  1. 参数是promise实例
    返回这个实例
  2. 参数是一个thenable对象
    thenable对象指的是具有then方法的对象
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function (value) {
  console.log(value);  // 42
});

Promise.resolve()方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then()方法。

  1. 参数不是具有then()方法的对象,或根本就不是对象
    如果参数是一个原始值,或者是一个不具有then()方法的对象,则Promise.resolve()方法返回一个新的 Promise 对象,状态为resolved。
const p = Promise.resolve('Hello');
p.then(function (s) {
  console.log(s)
});
//hello
  1. 不带任何参数
    直接返回一个resolved状态的 Promise 对象。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Promiese 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,语法上说,Pr...
    雨飞飞雨阅读 8,627评论 0 19
  • 摘自:阮一峰 http://es6.ruanyifeng.com/#docs/promise 一、首先,我们要弄明...
    泡杯感冒灵阅读 4,145评论 0 4
  • 00、前言Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区...
    夜幕小草阅读 6,380评论 0 12
  • Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函...
    neromous阅读 12,773评论 1 56
  • 一、Promise的含义 Promise在JavaScript语言中早有实现,ES6将其写进了语言标准,统一了用法...
    Alex灌汤猫阅读 4,237评论 0 2