1. 概念

  Promise对象用于异步(asynchronouss)计算,一个Promise对象代表着一个还未完成,但预期完成的操作。

2. 出现原因:

 1)  如果你需要通过ajax发送多次请求,而每一次请求依赖上一次请求返回的结果作为参数来继续下次的请求,这样的话,就需要这么写代码:

  

  上面的例子,假设请求C需要依赖B返回的数据,那么C需要放在B的success函数里面。同样的,A需要依赖B返回的数据,那么A也需要放在B的success函数里面。假设现在存在很多个请求,请求之前是相互的依赖关系,那么我们需要嵌套很多层,这样的话,代码的可读性就很差,不直观,调试起来也不方便,维护也不方便。

 2)  如果请求C需要依赖A和B的结果,而A,B是互相独立的,没有依赖关系,那么如果使用上面的实现方法,就使得A(B)需要依赖B(A)完成之后才能调用,这样需要更长的等待时间。

  所以,为了处理这种回调函数层层嵌套的问题(又称“回调地狱”),所以Promise就出现了。

3. 语法

  new Promise(function(resolve,reject){

  //操作…

  });

  Promise对象是全局对象,你也可以理解为一个类,创建Promise实例的时候,利用new关键字。其中,resolve和reject两个参数是函数对象。resolve是用于处理执行成功的场景,reject是用在处理执行失败的场景,一旦操作完成就可以调用这两个函数。具体的调用是通过then()方法来绑定操作后的处理程序,具体使用见之后的讲解。

4. 解析

Promise对象的三种状态:

 1)  pending:刚刚创建一个Promise实例的时候,表示初始化状态

 2)  fulfilled:resolve方法调用的时候,表示操作成功

 3)  rejected:reject方法调用的时候,表示操作失败

  pending状态的promise对象既可转换为带着一个成功值的fulfilled 状态,也可变为带着一个失败信息的 rejected 状态。当状态发生转换时,promise.then绑定的方法(函数句柄)就会被调用。(当绑定方法时,如果 promise对象已经处于 fulfilled 或 rejected 状态,那么相应的方法将会被立刻调用, 所以在异步操作的完成情况和它的绑定方法之间不存在竞争条件。)

  

(图片来源:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)

5. 属性

  Promise.length:长度属性,其值为1(构造参数的数目)

  Promise。prototype:Promise构造器的原型

6. 方法

 1)  Promise.then()方法:用于绑定处理操作后的处理程序。

  

 2)  Promise.catch()方法:用于处理操作异常后的页面。

  

 3)  then()和catch()综合使用的例子:

  

 4)  层层依赖用Promise处理:

   代码:

  1. let pro = new Promise(function(resolve,reject){
  2. if(true){
  3. resolve('操作成功');//此时resolve函数会返回值
  4. }
  5. else{
  6. reject('操作失败');
  7. }
  8. });
  9.  
  10. pro.then(requestA)
  11. .then(requestB)
  12. .then(requestC)
  13. .catch(requestError);
  14.  
  15. function requestA(res){
  16. console.log(res);//输出resolve返回的值-->操作成功
  17. console.log("请求A成功");
  18. return "请求A,下一步就是B你了";
  19. }
  20.  
  21. function requestB(res){
  22. console.log("上一步是"+res);
  23. console.log("请求B成功");
  24. return "请求B,下一步是C你了";
  25. }
  26.  
  27. function requestC(res){
  28. console.log("上一步是"+res);
  29. console.log("请求C成功");
  30. }
  31.  
  32. function requestError(){
  33. console.log("请求失败");
  34. }

  

  结果:

  

  解析:上面的例子中:先创建一个实例,还声明了4个函数,其中三个是分别代表着请求A、B、C的;有了then方法,按照调用顺序,很直观的完成了三个操作的绑定。并且,如果请求B依赖请求A的结果,那么,可以在请求A的程序用return语句把需要的数据作为参数,传递给下一个请求。

  (图片例子来源微信公众号:“web前端教程”)

 5)  Promise.all()方法:接受一个数组作为参数,数组的元素是Promise实例对象,当参数中的实例对象的状态都为fulfilled时,Promise.all()才会有返回。

  

  解析:pro2先进入成功fulfilled状态,才是Promise.all()还不能进入then方法,等到5s之后,pro1进入成功fulfilled状态,Promise.all()才进入then方法,才输出结果:["实例1操作成功", "实例2操作成功"]

 6)  Promise.race():接受一个数组作为参数,数组的元素是Promise实例对象,当参数中的实例对象有一个状态(无论是fulfilled还是rejected)发生变化的时候,Promise.race()就会进入then方法。

  

7. 原型

 属性:

  Promise.prototype.constructor:返回创建了实例原型的函数.  默认为 Promise 函数

 方法:

  Promise.prototype.catch(onRejected):添加一个否定(rejection) 回调到当前 promise, 返回一个新的promise。如果这个回调被调用,新 promise 将以它的返回值来resolve,否则如果当前promise 进入fulfilled状态,则以当前promise的肯定结果作为新promise的肯定结果.

  Promise.prototype.then(onFulfilled, onRejected):添加肯定和否定回调到当前 promise, 返回一个新的 promise, 将以回调的返回值 来resolve.

8. 例子

 参考的例子:

  1. <div id="log"></div>
  2. <script>
  3. 'use strict';
  4. var promiseCount = 0;
  5. function testPromise() {
  6. var thisPromiseCount = ++promiseCount;
  7. var log = document.getElementById('log');
  8. log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 开始(同步代码开始)<br/>');
  9. // 我们创建一个新的promise: 然后用'result'字符串完成这个promise (3秒后)
  10. var p1 = new Promise(function (resolve, reject) {
  11. // 完成函数带着完成(resolve)或拒绝(reject)promise的能力被执行
  12. log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise开始(异步代码开始)<br/>');
  13.  
  14. // 这只是个创建异步完成的示例
  15. window.setTimeout(function () {
  16. // 我们满足(fullfil)了这个promise!
  17. resolve(thisPromiseCount)
  18. }, Math.random() * 2000 + 1000);
  19. });
  20. // 定义当promise被满足时应做什么
  21. p1.then(function (val) {
  22. // 输出一段信息和一个值
  23. log.insertAdjacentHTML('beforeend', val + ') Promise被满足了(异步代码结束)<br/>');
  24. });
  25.  
  26. log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 建立了Promise(同步代码结束)<br/><br/>');
  27. }
  28. testPromise();
  29. testPromise();
  30. testPromise();

 结果:

  

 另一个比较好的例子:

  https://github.com/mdn/promises-test/blob/gh-pages/index.html

9. 总结

 Promise是一个让开发者更合理、更规范地用于处理异步操作的对象。

10. 参考资料

  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

  https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML

11. 接下来的安排

  ajax源码运用

  结合promise与ajax源码运用

ECMAScript6的Promise对象的更多相关文章

  1. 关于promise对象的笔记

    1.promise对象是ECMAScript6的新特性,很多新的JS框架都有它的实现和应用 2.promise常用于异步调用(ajax)中 3.promise主要用于解决回调函数层层嵌套的写法 4.要 ...

  2. angular学习笔记(二十八-附2)-$http,$resource中的promise对象

    下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource) ...

  3. ES6深入学习记录(二)promise对象相关

    1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件更合理和强大.ES6将其写进了语言标准,统一了用法,原生提供了promise对象. 所谓Promis ...

  4. es6中的promise对象

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

  5. ES6的promise对象应该这样用

    ES6修补了一位Js修真者诸多的遗憾. 曾几何时,我这个小白从js非阻塞特性的坑中爬出来,当我经历了一些回调丑陋的写法和优化的尝试之后,我深深觉得js对于多线程阻塞式的开发语言而言,可能有着其太明显的 ...

  6. Angularjs promise对象解析

    1.先来看一段Demo,看完这个demo你可以思考下如果使用$.ajax如何处理同样的逻辑,使用ng的promise有何优势? var ngApp=angular.module('ngApp',[]) ...

  7. JavaScript异步编程(1)- ECMAScript 6的Promise对象

    JavaScript的Callback机制深入人心.而ECMAScript的世界同样充斥的各种异步操作(异步IO.setTimeout等).异步和Callback的搭载很容易就衍生"回调金字 ...

  8. Promise对象

    1.Promise思想:每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程.这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用. ...

  9. angularJS中的Promise对象($q)的深入理解

    原文链接:a better way to learn AngularJS - promises AngularJS通过内置的$q服务提供Promise编程模式.通过将异步函数注册到promise对象, ...

随机推荐

  1. linux下安装kears

    2. 安装python基础开发包 # 系统升级 sudo apt update sudo apt upgrade sudo apt install -y python-dev python-pip p ...

  2. 大毕设-MATLAB-常用知识回顾

    要用到FIR滤波器和抽样器下面研究这两个的Matlab实现: Fir滤波器: matlab上fir滤波器的关键字是fir1 在command窗口输入help fir1出现帮助文档: >> ...

  3. oracle 批量插入-支持序列自增

    1.创建表.序列 -- Create table create table test_batch ( id number not null, name ), account ) ) -- Create ...

  4. mysql 存储过程 游标的使用

    BEGINDECLARE id long;DECLARE Done INT DEFAULT 0;DECLARE userids CURSOR FOR SELECT userid from info_u ...

  5. java 访问mysql 实例

    前提条件: 1.安装eclipse,mysql.java jdk 2.安装mysql connect J  (我安装的版本是mysql connect J 5.1.39) 3.配置java环境变量 4 ...

  6. 关于c#的事件如何使用

    c#的委托delegate事件的详细使用 一.无参数,无返回的委托事件 委托事件类.事件的发生源.1.声明委托  2定义事件 3具体方法 public class Test { // …. publi ...

  7. 未能正确加载“RoslynPackage”包

    一打开新建程序或者打开项目就报错,原因是安装的组件或者模板丢失或者有问题,在这一过程加载组件必定会产生错误,以下为解决方法: 1.重命名以下文件夹C:\Users\moonlight\Local Se ...

  8. css中clip-path属性的运用

    今天看到一位同学的需求,要在一个div中加一个小尖尖,对话时发的图片,旁边这个三角是怎么实现与图片的颜色一致,效果如下: 当然,解决这个问题有各种奇淫巧技,现在我们来看一个css属性clip-path ...

  9. grep使用多个查询条件--或

    [root@mail ~]# grep 'usrquota\|grpquota' /etc/fstabLABEL=/1                /                       e ...

  10. R语言画图,根据正负值画不同颜色,并且画水平线或者垂直线

    col=ifelse(x<0, "blue", "red") #如果x值为负值,用蓝色表示,反之,用红色表示 abline(v=0,col="g ...