1. 异步回调

1.1 回调地狱

在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的回调地狱

1.2 并行结果

如果几个异步操作之间并没有前后顺序之分,但需要等多个异步操作都完成后才能执行后续的任务,无法实现并行节约时间

2. Promise

Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做,例如网络请求、读取本地文件等 

3. Promise的三种状态

  • Pending Promise对象实例创建时候的初始状态
  • Fulfilled 可以理解为成功的状态
  • Rejected 可以理解为失败的状态

then 方法就是用来指定Promise 对象的状态改变时确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)

4. 构造一个Promise

4.1 使用Promise

  1. let promise = new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. if(Math.random()>0.5)
  4. resolve('This is resolve!');
  5. else
  6. reject('This is reject!');
  7. }, 1000);
  8. });
  9. promise.then(Fulfilled,Rejected)
  • 构造一个Promise实例需要给Promise构造函数传入一个函数。
  • 传入的函数需要有两个形参,两个形参都是function类型的参数。
    • 第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作
    • 第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作

4.2 es5模拟Promise

  1. function Promise(fn) {
  2. fn((data)=> {
  3. this.success(data);
  4. }, (error)=> {
  5. this.error();
  6. });
  7. }
  8.  
  9. Promise.prototype.resolve = function (data) {
  10. this.success(data);
  11. }
  12.  
  13. Promise.prototype.reject = function (error) {
  14. this.error(error);
  15. }
  16.  
  17. Promise.prototype.then = function (success, error) {
  18. this.success = success;
  19. this.error = error;
  20. }

4.3 es6模拟Promise

  1. class Promise {
  2. constructor(fn) {
  3. fn((data)=> {
  4. this.success(data);
  5. }, (error)=> {
  6. this.error();
  7. });
  8. }
  9.  
  10. resolve(data) {
  11. this.success(data);
  12. }
  13.  
  14. reject(error) {
  15. this.error(error);
  16. }
  17.  
  18. then(success, error) {
  19. this.success = success;
  20. this.error = error;
  21. console.log(this);
  22. }
  23. }

5. promise 做为函数的返回值

  1. function ajaxPromise (queryUrl) {
  2. return new Promise((resolve, reject) => {
  3. let xhr = new XMLHttpRequest();
  4. xhr.open('GET', queryUrl, true);
  5. xhr.send(null);
  6. xhr.onreadystatechange = () => {
  7. if (xhr.readyState === 4) {
  8. if (xhr.status === 200) {
  9. resolve(xhr.responseText);
  10. } else {
  11. reject(xhr.responseText);
  12. }
  13. }
  14. }
  15. });
  16. }
  17.  
  18. ajaxPromise('http://www.baidu.com')
  19. .then((value) => {
  20. console.log(value);
  21. })
  22. .catch((err) => {
  23. console.error(err);
  24. });

6.promise的链式调用

  • 每次调用返回的都是一个新的Promise实例
  • 链式调用的参数通过返回值传递

then可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个Promise对象

  1. readFile('1.txt').then(function (data) {
  2. console.log(data);
  3. return data;
  4. }).then(function (data) {
  5. console.log(data);
  6. return readFile(data);
  7. }).then(function (data) {
  8. console.log(data);
  9. }).catch(function(err){
  10. console.log(err);
  11. });

7.promise API

7.1 Promise.all

  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
    1. Promise.all([p1, p2]).then(function (result) {
    2. console.log(result); // [ '2.txt', '2' ]
    3. });

    不管两个promise谁先完成,Promise.all 方法会按照数组里面的顺序将结果返回

7.2 Promise.race

  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
    1. Promise.race([p1, p2]).then(function (result) {
    2. console.log(result); // [ '2.txt', '2' ]
    3. });

    7.3 Promise.resolve

    返回一个Promise实例,这个实例处于resolve状态。

根据传入的参数不同有不同的功能:

  • 值(对象、数组、字符串等):作为resolve传递出去的值
  • Promise实例:原封不动返回

7.4 Promise.reject

返回一个Promise实例,这个实例处于reject状态。

  • 参数一般就是抛出的错误信息。

8. q

Q是一个在Javascript中实现promise的模块

8.1 q的基本用法

  1. var Q = require('q');
  2. var fs = require('fs');
  3. function read(filename) {
  4. var deferred = Q.defer();
  5. fs.readFile(filename,'utf8', function (err, data) {
  6. if(err){
  7. deferred.reject(err);
  8. }else{
  9. deferred.resolve(data);
  10. }
  11. });
  12. return deferred.promise;
  13. }
  14.  
  15. read('1.txt1').then(function(data){
  16. console.log(data);
  17. },function(error){
  18. console.error(error);
  19. });

8.2 q的简单实现

  1. module.exports = {
  2. defer(){
  3. var _success,_error;
  4. return {
  5. resolve(data){
  6. _success(data);
  7. },
  8. reject(err){
  9. _error(err);
  10. },
  11. promise:{
  12. then(success,error){
  13. _success = success;
  14. _error = error;
  15. }
  16. }
  17. }
  18. }
  19. }

8.3 q的实现

  1. var defer = function () {
  2. var pending = [], value;
  3. return {
  4. resolve: function (_value) {
  5. if (pending) {
  6. value = _value;
  7. for (var i = 0, ii = pending.length; i < ii; i++) {
  8. var callback = pending[i];
  9. callback(value);
  10. }
  11. pending = undefined;
  12. }
  13. },
  14. promise: {
  15. then: function (callback) {
  16. if (pending) {
  17. pending.push(callback);
  18. } else {
  19. callback(value);
  20. }
  21. }
  22. }
  23. };
  24. };

9. bluebird

实现 promise 标准的库是功能最全,速度最快的一个库

9.1 bluebird经典使用

  1. var Promise = require('./bluebird');
  2.  
  3. var readFile = Promise.promisify(require("fs").readFile);
  4. readFile("1.txt", "utf8").then(function(contents) {
  5. console.log(contents);
  6. })
  7.  
  8. var fs = Promise.promisifyAll(require("fs"));
  9.  
  10. fs.readFileAsync("1.txt", "utf8").then(function (contents) {
  11. console.log(contents);
  12. })

9.2 bluebird简单实现

  1. module.exports = {
  2. promisify(fn){
  3. return function () {
  4. var args = Array.from(arguments);
  5. return new Promise(function (resolve, reject) {
  6. fn.apply(null, args.concat(function (err) {
  7. if (err) {
  8. reject(err);
  9. } else {
  10. resolve(arguments[1])
  11. }
  12. }));
  13. })
  14. }
  15. },
  16. promisifyAll(obj){
  17. for(var attr in obj){
  18. if(obj.hasOwnProperty(attr) && typeof obj[attr] =='function'){
  19. obj[attr+'Async'] = this.promisify(obj[attr]);
  20. }
  21. }
  22. return obj;
  23. }
  24. }

10. 动画

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>move</title>
  6. <style>
  7. .square{
  8. width:40px;
  9. height:40px;
  10. border-radius: 50%;
  11. }
  12. .square1{
  13. background-color: red;
  14. }
  15. .square2{
  16. background-color: yellow;
  17. }
  18. .square3{
  19. background-color: blue;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="square square1" style="margin-left: 0"></div>
  25. <div class="square square2" style="margin-left: 0"></div>
  26. <div class="square square3" style="margin-left: 0"></div>
  27. </body>
  28. <script>
  29. var square1 = document.querySelector('.square1');
  30. var square2 = document.querySelector('.square2');
  31. var square3 = document.querySelector('.square3');
  32.  
  33. /*function move(element,target,resolve){
  34. let timer = setInterval(function(){
  35. var marginLeft = parseInt(element.style.marginLeft, 10);
  36. if(marginLeft == target){
  37. resolve();
  38. }else{
  39. element.style.marginLeft = ++marginLeft+'px';
  40. }
  41. },13);
  42. }*/
  43. function move(element,target,resolve){
  44. let current = 0;
  45. let timer = setInterval(function(){
  46. element.style.transform=`translateX(${++current}px)`;
  47. if(current>target){
  48. clearInterval(timer);
  49. resolve();
  50. };
  51. },13);
  52. }
  53. function animate(element,target){
  54. return new Promise(function(resolve,reject){
  55. move(element,target,resolve);
  56. });
  57. }
  58. animate(square1,100)
  59. .then(function(){
  60. return animate(square2,100);
  61. })
  62. .then(function(){
  63. return animate(square3,100);
  64. });
  65. </script>
  66. </html>

11. co

11.1 co初体验

  1. let fs = require('fs');
  2. function getNumber(){
  3. return new Promise(function (resolve,reject) {
  4. setTimeout(function(){
  5. let number = Math.random();
  6. if(number >.5){
  7. resolve(number);
  8. }else{
  9. reject('数字太小');
  10. }
  11. },1000);
  12. });
  13. }
  14. function *read(){
  15. let a = yield getNumber();
  16. console.log(a);
  17. let b = yield 'b';
  18. console.log(b);
  19. let c = yield getNumber();
  20. console.log(c);
  21. }
  22.  
  23. function co(gen){
  24. return new Promise(function(resolve,reject){
  25. let g = gen();
  26. function next(lastValue){
  27. let {done,value} = g.next(lastValue);
  28. if(done){
  29. resolve(lastValue);
  30. }else{
  31. if(value instanceof Promise){
  32. value.then(next,function(val){
  33. reject(val);
  34. });
  35. }else{
  36. next(value);
  37. }
  38. }
  39. }
  40. next();
  41. });
  42. }
  43. co(read).then(function(data){
  44. console.log(data);
  45. },function(reason){
  46. console.log(reason);
  47. });

11.2 co连续读文件

  1. let fs = require('fs');
  2. function readFile(filename){
  3. return new Promise(function (resolve,reject) {
  4. fs.readFile(filename,'utf8',function(err,data){
  5. if(err)
  6. reject(err);
  7. else
  8. resolve(data);
  9. })
  10. });
  11. }
  12. function *read(){
  13. let a = yield readFile('./1.txt');
  14. console.log(a);
  15. let b = yield readFile('./2.txt');
  16. console.log(b);
  17. }
  18.  
  19. function co(gen){
  20. let g = gen();
  21. function next(val){
  22. let {done,value} = g.next(val);
  23. if(!done){
  24. value.then(next);
  25. }
  26. }
  27. next();
  28. }

12. Promise/A+完整实现

  1. function Promise(executor) {
  2. let self = this;
  3. self.status = "pending";
  4. self.value = undefined;
  5. self.onResolvedCallbacks = [];
  6. self.onRejectedCallbacks = [];
  7. function resolve(value) {
  8. if (value instanceof Promise) {
  9. return value.then(resolve, reject)
  10. }
  11. setTimeout(function () { // 异步执行所有的回调函数
  12. if (self.status == 'pending') {
  13. self.value = value;
  14. self.status = 'resolved';
  15. self.onResolvedCallbacks.forEach(item => item(value));
  16. }
  17. });
  18.  
  19. }
  20.  
  21. function reject(value) {
  22. setTimeout(function () {
  23. if (self.status == 'pending') {
  24. self.value = value;
  25. self.status = 'rejected';
  26. self.onRejectedCallbacks.forEach(item => item(value));
  27. }
  28. });
  29. }
  30.  
  31. try {
  32. executor(resolve, reject);
  33. } catch (e) {
  34. reject(e);
  35. }
  36. }
  37. function resolvePromise(promise2, x, resolve, reject) {
  38. if (promise2 === x) {
  39. return reject(new TypeError('循环引用'));
  40. }
  41. let then, called;
  42.  
  43. if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {
  44. try {
  45. then = x.then;
  46. if (typeof then == 'function') {
  47. then.call(x, function (y) {
  48. if (called)return;
  49. called = true;
  50. resolvePromise(promise2, y, resolve, reject);
  51. }, function (r) {
  52. if (called)return;
  53. called = true;
  54. reject(r);
  55. });
  56. } else {
  57. resolve(x);
  58. }
  59. } catch (e) {
  60. if (called)return;
  61. called = true;
  62. reject(e);
  63. }
  64. } else {
  65. resolve(x);
  66. }
  67. }
  68. Promise.prototype.then = function (onFulfilled, onRejected) {
  69. let self = this;
  70. onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : function (value) {
  71. return value
  72. };
  73. onRejected = typeof onRejected == 'function' ? onRejected : function (value) {
  74. throw value
  75. };
  76. let promise2;
  77. if (self.status == 'resolved') {
  78. promise2 = new Promise(function (resolve, reject) {
  79. setTimeout(function () {
  80. try {
  81. let x = onFulfilled(self.value);
  82. resolvePromise(promise2, x, resolve, reject);
  83. } catch (e) {
  84. reject(e);
  85. }
  86. });
  87.  
  88. });
  89. }
  90. if (self.status == 'rejected') {
  91. promise2 = new Promise(function (resolve, reject) {
  92. setTimeout(function () {
  93. try {
  94. let x = onRejected(self.value);
  95. resolvePromise(promise2, x, resolve, reject);
  96. } catch (e) {
  97. reject(e);
  98. }
  99. });
  100. });
  101. }
  102. if (self.status == 'pending') {
  103. promise2 = new Promise(function (resolve, reject) {
  104. self.onResolvedCallbacks.push(function (value) {
  105. try {
  106. let x = onFulfilled(value);
  107. resolvePromise(promise2, x, resolve, reject);
  108. } catch (e) {
  109. reject(e);
  110. }
  111. });
  112. self.onRejectedCallbacks.push(function (value) {
  113. try {
  114. let x = onRejected(value);
  115. resolvePromise(promise2, x, resolve, reject);
  116. } catch (e) {
  117. reject(e);
  118. }
  119. });
  120. });
  121. }
  122. return promise2;
  123. }
  124. Promise.prototype.catch = function (onRejected) {
  125. return this.then(null, onRejected);
  126. }
  127. Promise.all = function (promises) {
  128. return new Promise(function (resolve, reject) {
  129. let result = [];
  130. let count = 0;
  131. for (let i = 0; i < promises.length; i++) {
  132. promises[i].then(function (data) {
  133. result[i] = data;
  134. if (++count == promises.length) {
  135. resolve(result);
  136. }
  137. }, function (err) {
  138. reject(err);
  139. });
  140. }
  141. });
  142. }
  143.  
  144. Promise.deferred = Promise.defer = function () {
  145. var defer = {};
  146. defer.promise = new Promise(function (resolve, reject) {
  147. defer.resolve = resolve;
  148. defer.reject = reject;
  149. })
  150. return defer;
  151. }
  152. /**
  153. * npm i -g promises-aplus-tests
  154. * promises-aplus-tests Promise.js
  155. */
  156. try {
  157. module.exports = Promise
  158. } catch (e) {
  159. }

13. 资源

关于Promise的详细总结的更多相关文章

  1. 关于promise的详细讲解

    到处是回调函数,代码非常臃肿难看, Promise 主要用来解决这种编程方式, 将某些代码封装于内部. Promise 直译为"承诺",但一般直接称为 Promise; 代码的可读 ...

  2. 一道关于Promise应用的面试题

    题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次:如何让三个灯不断交替重复亮灯?(用Promse实现) 三个亮灯函数已经存在: function red(){ console.log('red') ...

  3. 介绍axios和promise

    今天小编为大家带来 axios 和promise的详细讲解,包含 axios的使用方法 多种写法,封装 以及 promise的详细讲解,项目中如何运用等,会一一的为大家讲解清楚. 一.axios的介绍 ...

  4. Promise、Generator、Async有什么区别?

    前言 我们知道Promise与Async/await函数都是用来解决JavaScript中的异步问题的,从最开始的回调函数处理异步,到Promise处理异步,到Generator处理异步,再到Asyn ...

  5. [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-layers简介

    [官方文档:https://developers.arcgis.com/javascript/latest/sample-code/intro-layers/index.html] 一.Intro t ...

  6. angularjs和ajax的结合使用 (三)

    转眼九月份了,忙忙碌碌 发现今年还没开过张,写一篇吧. 15年在空闲时就倒腾过angularjs那玩意儿 ,觉得还是挺好的,李金龙那厚厚的一本书,只不过没有系统化应用.最主要的是原来有一个东西没有用到 ...

  7. Vue 入门之 Vuex 实战

    Vue 入门之 Vuex 实战 引言 Vue 组件化做的确实非常彻底,它独有的 vue 单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其 Vue 组件设计的就 ...

  8. redux基础(1)

    redux ps:每个案例都是接着上一个案例写的 主要以案例讲解如何使用,具体概念请参考如下: 基本概念参考1 基本概念参考2 案例源码戳这里 一.Store.Action.Reducer简介 Sto ...

  9. async/await的使用以及注意事项

    使用 async / await, 搭配 promise, 可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性. 本文介绍 async / await 的基本用法和一些注意事项. a ...

随机推荐

  1. C# MVC js 跨域

    js 跨域: 第一种解决方案(服务端解决跨域问题): 跨域是浏览器的一种安全策略,是浏览器自身做的限制,不允许用户访问不同域名或端口或协议的网站数据. 只有域名(主域名[一级域名]和二级域名).端口号 ...

  2. TortoiseSvn介绍 客户端

    转载自:http://www.cnblogs.com/lyhabc/articles/2482381.html TortoiseSvn 是 Subversion 版本控制系统的一个免费开源客户端,可以 ...

  3. POJ Oulipo KMP 模板题

    http://poj.org/problem?id=3461 Oulipo Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4 ...

  4. linux下支持托盘的邮件客户端Sylpheed

    在网上搜索了很多客户端想支持系统托盘,发现一个很不错的邮件客户端Sylpheed.设置方式和foxmail很像,最为重要的是支持系统托盘,很方便,默认没有开启,简单设置下:配置->通用首选项-& ...

  5. U-BOOT概述及源码分析(一)

    嵌入式Linux系统从软件角度通常可以分为以下4个层次: 引导加载程序 | Linux内核 | 文件系统 | 用户应用程序 嵌入式Linux系统中典型分区结构: 正常启动过程中,Bootloader首 ...

  6. SpringBoot 静态资源 加载位置

    1.配置自定义拦截器 /** * Copyright (C), 2017-2018, XXX有限公司 * FileName: WebConfig * Author: 丶Zh1Guo * Date: 2 ...

  7. Logback自定义日志输出内容

    场景 一般情况下,日志打印的内容都是根据配置文件中配置的pattern格式指定好的.在我们调用logger.info(), logger.debug()等日志打印方法时,打印的内容格式与配置文件中的p ...

  8. SPSS提示“列表中不同意存在字符串变量”的解决方法

    今天用SPSS对一些数据进行主成分分析,SPSS 19.0进行主成分分析的方法是:分析--降维--因子分析,可是当导入一些变量的时候.就会弹出窗体说"列表中不同意存在字符串变量", ...

  9. 如何覆盖GCE的DHCP MTU选项

     如何覆盖GCE的DHCP MTU选项 在GCE上托管的Linux IPSec隧道不能打开谷歌,这与MTU有关.谷歌管理员认为"改变这个值是一件困难的事情"https://cl ...

  10. jQuery11 data() : 数据缓存

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...