Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。简单点说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。

它的一般表示形式为:

  1. new Promise(
  2. /* executor */
  3. function(resolve, reject) {
  4. if (/* success */) {
  5. // ...执行代码
  6. resolve();
  7. } else { /* fail */
  8. // ...执行代码
  9. reject();
  10. }
  11. }
  12. );

其中,Promise中的参数executor是一个执行器函数,它有两个参数resolvereject。它内部通常有一些异步操作,如果异步操作成功,则可以调用resolve()来将该实例的状态置为fulfilled,即已完成的,如果一旦失败,可以调用reject()来将该实例的状态置为rejected,即失败的。

我们可以把Promise对象看成是一条工厂的流水线,对于流水线来说,从它的工作职能上看,它只有三种状态,一个是初始状态(刚开机的时候),一个是加工产品成功,一个是加工产品失败(出现了某些故障)。同样对于Promise对象来说,它也有三种状态:

  1. pending
    初始状态,也称为未定状态,就是初始化Promise时,调用executor执行器函数后的状态。
  2. fulfilled
    完成状态,意味着异步操作成功。
  3. rejected
    失败状态,意味着异步操作失败。

它只有两种状态可以转化,即

  • 操作成功
    pending -> fulfilled
  • 操作失败
    pending -> rejected

并且这个状态转化是单向的,不可逆转,已经确定的状态(fulfilled/rejected)无法转回初始状态(pending)。

方法

Promise.prototype.then()

Promise对象含有then方法,then()调用后返回一个Promise对象,意味着实例化后的Promise对象可以进行链式调用,而且这个then()方法可以接收两个函数,一个是处理成功后的函数,一个是处理错误结果的函数。

如下:

  1. var promise1 = new Promise(function(resolve, reject) {
  2. // 2秒后置为接收状态
  3. setTimeout(function() {
  4. resolve('success');
  5. }, 2000);
  6. });
  7. promise1.then(function(data) {
  8. console.log(data); // success
  9. }, function(err) {
  10. console.log(err); // 不执行
  11. }).then(function(data) {
  12. // 上一步的then()方法没有返回值
  13. console.log('链式调用:' + data); // 链式调用:undefined
  14. }).then(function(data) {
  15. // ....
  16. });

在这里我们主要关注promise1.then()方法调用后返回的Promise对象的状态,是pending还是fulfilled,或者是rejected?

返回的这个Promise对象的状态主要是根据promise1.then()方法返回的值,大致分为以下几种情况:

  1. 如果then()方法中返回了一个参数值,那么返回的Promise将会变成接收状态。
  2. 如果then()方法中抛出了一个异常,那么返回的Promise将会变成拒绝状态。
  3. 如果then()方法调用resolve()方法,那么返回的Promise将会变成接收状态。
  4. 如果then()方法调用reject()方法,那么返回的Promise将会变成拒绝状态。
  5. 如果then()方法返回了一个未知状态(pending)的Promise新实例,那么返回的新Promise就是未知状态。
  6. 如果then()方法没有明确指定的resolve(data)/reject(data)/return data时,那么返回的新Promise就是接收状态,可以一层一层地往下传递。

转换实例如下:

  1. var promise2 = new Promise(function(resolve, reject) {
  2. // 2秒后置为接收状态
  3. setTimeout(function() {
  4. resolve('success');
  5. }, 2000);
  6. });
  7. promise2
  8. .then(function(data) {
  9. // 上一个then()调用了resolve,置为fulfilled态
  10. console.log('第一个then');
  11. console.log(data);
  12. return '2';
  13. })
  14. .then(function(data) {
  15. // 此时这里的状态也是fulfilled, 因为上一步返回了2
  16. console.log('第二个then');
  17. console.log(data); // 2
  18. return new Promise(function(resolve, reject) {
  19. reject('把状态置为rejected error'); // 返回一个rejected的Promise实例
  20. });
  21. }, function(err) {
  22. // error
  23. })
  24. .then(function(data) {
  25. /* 这里不运行 */
  26. console.log('第三个then');
  27. console.log(data);
  28. // ....
  29. }, function(err) {
  30. // error回调
  31. // 此时这里的状态也是fulfilled, 因为上一步使用了reject()来返回值
  32. console.log('出错:' + err); // 出错:把状态置为rejected error
  33. })
  34. .then(function(data) {
  35. // 没有明确指定返回值,默认返回fulfilled
  36. console.log('这里是fulfilled态');
  37. });

Promise.prototype.catch()

catch()方法和then()方法一样,都会返回一个新的Promise对象,它主要用于捕获异步操作时出现的异常。因此,我们通常省略then()方法的第二个参数,把错误处理控制权转交给其后面的catch()函数,如下:

  1. var promise3 = new Promise(function(resolve, reject) {
  2. setTimeout(function() {
  3. reject('reject');
  4. }, 2000);
  5. });
  6. promise3.then(function(data) {
  7. console.log('这里是fulfilled状态'); // 这里不会触发
  8. // ...
  9. }).catch(function(err) {
  10. // 最后的catch()方法可以捕获在这一条Promise链上的异常
  11. console.log('出错:' + err); // 出错:reject
  12. });

Promise.all()

Promise.all()接收一个参数,它必须是可以迭代的,比如数组

它通常用来处理一些并发的异步操作,即它们的结果互不干扰,但是又需要异步执行。它最终只有两种状态:成功或者失败

它的状态受参数内各个值的状态影响,即里面状态全部为fulfilled时,它才会变成fulfilled,否则变成rejected

成功调用后返回一个数组,数组的值是有序的,即按照传入参数的数组的值操作后返回的结果。如下:

  1. // 置为fulfilled状态的情况
  2. var arr = [1, 2, 3];
  3. var promises = arr.map(function(e) {
  4. return new Promise(function(resolve, reject) {
  5. resolve(e * 5);
  6. });
  7. });
  8. Promise.all(promises).then(function(data) {
  9. // 有序输出
  10. console.log(data); // [5, 10, 15]
  11. console.log(arr); // [1, 2, 3]
  12. });
  1. // 置为rejected状态的情况
  2. var arr = [1, 2, 3];
  3. var promises2 = arr.map(function(e) {
  4. return new Promise(function(resolve, reject) {
  5. if (e === 3) {
  6. reject('rejected');
  7. }
  8. resolve(e * 5);
  9. });
  10. });
  11. Promise.all(promises2).then(function(data) {
  12. // 这里不会执行
  13. console.log(data);
  14. console.log(arr);
  15. }).catch(function(err) {
  16. console.log(err); // rejected
  17. });

Promise.race()

Promise.race()和Promise.all()类似,都接收一个可以迭代的参数,但是不同之处是Promise.race()的状态变化不是全部受参数内的状态影响,一旦参数内有一个值的状态发生的改变,那么该Promise的状态就是改变的状态。就跟race单词的字面意思一样,谁跑的快谁赢。如下:

  1. var p1 = new Promise(function(resolve, reject) {
  2. setTimeout(resolve, 300, 'p1 doned');
  3. });
  4. var p2 = new Promise(function(resolve, reject) {
  5. setTimeout(resolve, 50, 'p2 doned');
  6. });
  7. var p3 = new Promise(function(resolve, reject) {
  8. setTimeout(reject, 100, 'p3 rejected');
  9. });
  10. Promise.race([p1, p2, p3]).then(function(data) {
  11. // 显然p2更快,所以状态变成了fulfilled
  12. // 如果p3更快,那么状态就会变成rejected
  13. console.log(data); // p2 doned
  14. }).catch(function(err) {
  15. console.log(err); // 不执行
  16. });

Promise.resolve()

Promise.resolve()接受一个参数值,可以是普通的值具有then()方法的对象Promise实例。正常情况下,它返回一个Promise对象,状态为fulfilled。但是,当解析时发生错误时,返回的Promise对象将会置为rejected态。如下:

  1. // 参数为普通值
  2. var p4 = Promise.resolve(5);
  3. p4.then(function(data) {
  4. console.log(data); // 5
  5. });
  6. // 参数为含有then()方法的对象
  7. var obj = {
  8. then: function() {
  9. console.log('obj 里面的then()方法');
  10. }
  11. };
  12. var p5 = Promise.resolve(obj);
  13. p5.then(function(data) {
  14. // 这里的值时obj方法里面返回的值
  15. console.log(data); // obj 里面的then()方法
  16. });
  17. // 参数为Promise实例
  18. var p6 = Promise.resolve(7);
  19. var p7 = Promise.resolve(p6);
  20. p7.then(function(data) {
  21. // 这里的值时Promise实例返回的值
  22. console.log(data); // 7
  23. });
  24. // 参数为Promise实例,但参数是rejected态
  25. var p8 = Promise.reject(8);
  26. var p9 = Promise.resolve(p8);
  27. p9.then(function(data) {
  28. // 这里的值时Promise实例返回的值
  29. console.log('fulfilled:'+ data); // 不执行
  30. }).catch(function(err) {
  31. console.log('rejected:' + err); // rejected: 8
  32. });

Promise.reject()

Promise.reject()和Promise.resolve()正好相反,它接收一个参数值reason,即发生异常的原因。此时返回的Promise对象将会置为rejected态。如下:

  1. var p10 = Promise.reject('手动拒绝');
  2. p10.then(function(data) {
  3. console.log(data); // 这里不会执行,因为是rejected态
  4. }).catch(function(err) {
  5. console.log(err); // 手动拒绝
  6. }).then(function(data) {
  7. // 不受上一级影响
  8. console.log('状态:fulfilled'); // 状态:fulfilled
  9. });

总之,除非Promise.then()方法内部抛出异常或者是明确置为rejected态,否则它返回的Promise的状态都是fulfilled态,即完成态,并且它的状态不受它的上一级的状态的影响。

总结

大概常用的方法就写那么多,剩下的看自己实际需要再去了解。

解决Node回调地狱的不止有Promise,还有Generator和ES7提出的Async实现。

ES6关于Promise的用法的更多相关文章

  1. ES6关于Promise的用法详解

    Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...

  2. ES6的promise函数用法讲解

    总结:Promise函数的出现极大的解决了Js中的异步调用代码逻辑编写太过复杂的问题,Promise对象让异步调用函数的流程显得更加的优雅,也更容易编写. 举例: 1. 异步调用: 假设现在我的一个页 ...

  3. ES6语法 promise用法

    ES6语法 promise用法 function doSomething(){ return new Promise((resolve,reject)=>{ resolve('jjjj');// ...

  4. ES6之Promise用法详解

    一 前言 本文主要对ES6的Promise进行一些入门级的介绍.要想学习一个知识点,肯定是从三个方面出发,what.why.how.下面就跟着我一步步学习吧~ 二 什么是Promise 首先是what ...

  5. es6的promise用法详解

    es6的promise用法详解 promise 原理 promise是es6的异步编程解决方案, 是es6封装好的对象: 一个promise有三种状态:Pending(进行中).Resolved(已完 ...

  6. ES6中promise总结

    一.什么是ES6的Promise 讲太多也没有.直接在打印出来就好,console.dir(Promise) Promise 是一个构造函数,自身有all, reject, resolve 这几个眼熟 ...

  7. ES6新增"Promise"可避免回调地狱

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ...

  8. 关于ES6的Promise的使用深入理解

    ES6的promise对象研究 什么叫promise? Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码:让代码更加的直观. 那我们为什么 ...

  9. 整理一下Promise 的用法

    Promise 的定义 Pormise是JS的异步编程的一种解决方案,在ES6将其写进了语言标准,提供了原生的Promise对象. Promise简单来理解就是一个容器,里面存放着某个未来才会结束的事 ...

随机推荐

  1. Dynamics 365 Online-使用Azure Logic App 与 Dynamics 365 集成

    什么是Logic App? Azure Logic App 是微软发布的集成平台的产品,有助于生成,计划和自动完成工作流形式的流程,适合跨企业或组织集成,数据,系统和服务.与此同时,Logic App ...

  2. C#图解 (类和继承)

    所有的类都派生自object类 除了特殊的类object ,所有的类都是派生类,即使它们没有基类的规格说明.类object是唯一的非派生类,因为它是继承层次结构的基础. 一个类声明的基类规格说明只能有 ...

  3. .Net的垃圾回收机制(GC)之拙见——托管类型的垃圾回收

    各种语言的垃圾回收在IT界噪的沸沸扬扬,有极大的优化同时也有瓶颈. 而在.Net中的垃圾回收机制又是怎样的呢? 众所知周,.Net中的垃圾回收机制是由.Net Framework托管的,带给开发者最大 ...

  4. 记录一个古老的Sql分页过程

    /* 根据单位ID获取排班信息 For:WXX TIme:2017-11-22 */ ALTER proc [dbo].[proc_ScheduleInfo] )='', --单位ID )='', - ...

  5. 利用1.1.1.1进行DNS网络加速,仅需2分钟让网络更快

    NEWS 近日,Cloudflare 和 APNIC联合推出了1.1.1.1DNS网络加速. Cloudflare 运行全球规模最大.速度最快的网络之一.APNIC 是一个非营利组织,管理着亚太和大洋 ...

  6. Alpha冲刺总结

    团队成员 陈家权 031502107 赖晓连 031502118 雷晶 031502119 林巧娜 031502125 庄加鑫 031502147 一.项目预期计划及现实进展 项目预期计划 现实进展 ...

  7. 听翁恺老师mooc笔记(4)--指针的应用场景

    指针应用场景一:交换两个变量的值 在学习函数时,交换两个数的值,做一个swap函数,传递值进去,也可以将两个值交换过来,没问题,可是离开swap就没有用了,为什么?因为传进去的是两个值. #inclu ...

  8. 201621123057 《Java程序设计》第8周学习总结

    1. 本周学习总结 思维导图归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 ArrayList是允许重复的,但当用它来 ...

  9. XCode Build Settings中几种Search Paths

    Header search path:去查找头文件的路径,同在在你需要使用第三方库的时候,在这里设置你的头文件路径目录,如图 <code><span class="str& ...

  10. 日志 --BUG记录

    2014-12-15日 在做520wawa的免费推广   部署web应用时 错把path设置为"/*",导致启动tomcat时,导致错误 <Context path=&quo ...