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.  
  8. promise1.then(function(data) {
  9. console.log(data); // success
  10. }, function(err) {
  11. console.log(err); // 不执行
  12. }).then(function(data) {
  13. // 上一步的then()方法没有返回值
  14. console.log('链式调用:' + data); // 链式调用:undefined
  15. }).then(function(data) {
  16. // ....
  17. });

在这里我们主要关注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.  
  8. promise2
  9. .then(function(data) {
  10. // 上一个then()调用了resolve,置为fulfilled态
  11. console.log('第一个then');
  12. console.log(data);
  13. return '2';
  14. })
  15. .then(function(data) {
  16. // 此时这里的状态也是fulfilled, 因为上一步返回了2
  17. console.log('第二个then');
  18. console.log(data); //
  19.  
  20. return new Promise(function(resolve, reject) {
  21. reject('把状态置为rejected error'); // 返回一个rejected的Promise实例
  22. });
  23. }, function(err) {
  24. // error
  25. })
  26. .then(function(data) {
  27. /* 这里不运行 */
  28. console.log('第三个then');
  29. console.log(data);
  30. // ....
  31. }, function(err) {
  32. // error回调
  33. // 此时这里的状态也是fulfilled, 因为上一步使用了reject()来返回值
  34. console.log('出错:' + err); // 出错:把状态置为rejected error
  35. })
  36. .then(function(data) {
  37. // 没有明确指定返回值,默认返回fulfilled
  38. console.log('这里是fulfilled态');
  39. });

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.  
  7. promise3.then(function(data) {
  8. console.log('这里是fulfilled状态'); // 这里不会触发
  9. // ...
  10. }).catch(function(err) {
  11. // 最后的catch()方法可以捕获在这一条Promise链上的异常
  12. console.log('出错:' + err); // 出错:reject
  13. });

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.  
  9. Promise.all(promises).then(function(data) {
  10. // 有序输出
  11. console.log(data); // [5, 10, 15]
  12. console.log(arr); // [1, 2, 3]
  13. });
  14. // 置为rejected状态的情况
  15. var arr = [1, 2, 3];
  16. var promises2 = arr.map(function(e) {
  17. return new Promise(function(resolve, reject) {
  18. if (e === 3) {
  19. reject('rejected');
  20. }
  21. resolve(e * 5);
  22. });
  23. });
  24.  
  25. Promise.all(promises2).then(function(data) {
  26. // 这里不会执行
  27. console.log(data);
  28. console.log(arr);
  29. }).catch(function(err) {
  30. console.log(err); // rejected
  31. });

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

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. });
  6.  
  7. // 参数为含有then()方法的对象
  8. var obj = {
  9. then: function() {
  10. console.log('obj 里面的then()方法');
  11. }
  12. };
  13.  
  14. var p5 = Promise.resolve(obj);
  15. p5.then(function(data) {
  16. // 这里的值时obj方法里面返回的值
  17. console.log(data); // obj 里面的then()方法
  18. });
  19.  
  20. // 参数为Promise实例
  21. var p6 = Promise.resolve(7);
  22. var p7 = Promise.resolve(p6);
  23.  
  24. p7.then(function(data) {
  25. // 这里的值时Promise实例返回的值
  26. console.log(data); //
  27. });
  28.  
  29. // 参数为Promise实例,但参数是rejected态
  30. var p8 = Promise.reject(8);
  31. var p9 = Promise.resolve(p8);
  32.  
  33. p9.then(function(data) {
  34. // 这里的值时Promise实例返回的值
  35. console.log('fulfilled:'+ data); // 不执行
  36. }).catch(function(err) {
  37. console.log('rejected:' + err); // rejected: 8
  38. });

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对象

    Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...

  2. 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise

    第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...

  3. ES6中的Promise用法

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

  4. es6中的Promise学习

    关于Promise Promise实例一旦被创建就会被执行 Promise过程分为两个分支:pending=>resolved和pending=>rejected Promise状态改变后 ...

  5. ES6中的Promise使用方法与总结

    在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的. 但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回 ...

  6. [转]JS - Promise使用详解2(ES6中的Promise)

    原文地址:https://www.hangge.com/blog/cache/detail_1638.html 2015年6月, ES2015(即 ECMAScript 6.ES6) 正式发布.其中  ...

  7. ES6中的Promise和Generator详解

    目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...

  8. 理解ES6中的Promise

    一.Promise的作用 在ajax请求数据的过程中,我们可以异步拿到我们想要的数据,然后在回调中做相应的数据处理. 这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这 ...

  9. ES6中的Promise详解

    Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷. 定义 Promise 是一个对象,它用来标识 JavaScri ...

  10. es6中,promise使用过程的小总结

    参考资料传送门:戳一戳 1.是什么 Promise是异步编程的一种解决方案,有三种状态:pending(进行中).fulfilled(已成功)和rejected(已失败); 一般成功了状态用resol ...

随机推荐

  1. js中this应用

    this是js的一个关键字,随着函数使用场合不同,this的值会发生变化.但是总有一个原则,那就是this指的是调用函数的那个对象. 1.纯粹函数调用. function test() { this. ...

  2. MVC5新特性(一)之RouteAttribute打造自己的URL规则

    1.RouteAttribute概述 RouteAttribute的命名空间是System.Web.Mvc,区别与web api的RouteAttribute(它的命名空间是System.Web.Ht ...

  3. HDU 3790(两种权值的迪杰斯特拉算法)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=3790 最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    ...

  4. 循环获取某个class下的多个select的选中值

    //循环获取某个class下的多个select的选中值 function eachSelect(cla){ var val = ""; $("."+cla).e ...

  5. C#中如何利用操作符重载和转换操作符 (转载)

    操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...

  6. mac终端输入python默认打开python3

    *** 1. 终端打开.bash_profile文件 ***open ~/.bash_profile *** 2. .bash_profile文件内容 ***# Setting PATH for Py ...

  7. Struts2+AJAX+JQuery 实现用户登入与注册功能

    要求:必备知识:JAVA/Struts2,JS/JQuery,HTML/CSS基础语法:开发环境:MyEclipse 10 关于UI部分请查看下列链接,有详细制作步骤: 利用:before和:afte ...

  8. 【最新最全】为 iOS 和 Android 的真机和模拟器编译 Luajit 库

    编译 Luajit 库,的确是一个挑战.因为官网的教程,在当前版本的 Xcode 和 NDK 环境中,已经不适用了.以前只是编译了适用于真机的 Luajit 库.最近在尝试编译模拟器 Luajit 库 ...

  9. Eclipse部署Web项目,常用操作和常见错误的解决方案

    部署Web项目到tomcat 在eclipse中找到Servers项,打开服务器(F3)(建议直接删除服务器,重新建立再设置比较好)1.Servers Locations 中选择Use Tomcat ...

  10. 编写DVWA暴力破解High级别的Python脚本

    1. 过程(不查看源代码) 使用burpsuite或者owasp zap抓取数据包,可以看出页面执行过程如下: 首先获取上一次请求的token,然后sleep几秒,最后使用get方法提交验证. 2. ...