关于Promise的详细总结
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
- let promise = new Promise((resolve, reject) => {
- setTimeout(() => {
- if(Math.random()>0.5)
- resolve('This is resolve!');
- else
- reject('This is reject!');
- }, 1000);
- });
- promise.then(Fulfilled,Rejected)
- 构造一个Promise实例需要给Promise构造函数传入一个函数。
- 传入的函数需要有两个形参,两个形参都是function类型的参数。
- 第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作
- 第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作
4.2 es5模拟Promise
- function Promise(fn) {
- fn((data)=> {
- this.success(data);
- }, (error)=> {
- this.error();
- });
- }
- Promise.prototype.resolve = function (data) {
- this.success(data);
- }
- Promise.prototype.reject = function (error) {
- this.error(error);
- }
- Promise.prototype.then = function (success, error) {
- this.success = success;
- this.error = error;
- }
4.3 es6模拟Promise
- class Promise {
- constructor(fn) {
- fn((data)=> {
- this.success(data);
- }, (error)=> {
- this.error();
- });
- }
- resolve(data) {
- this.success(data);
- }
- reject(error) {
- this.error(error);
- }
- then(success, error) {
- this.success = success;
- this.error = error;
- console.log(this);
- }
- }
5. promise 做为函数的返回值
- function ajaxPromise (queryUrl) {
- return new Promise((resolve, reject) => {
- let xhr = new XMLHttpRequest();
- xhr.open('GET', queryUrl, true);
- xhr.send(null);
- xhr.onreadystatechange = () => {
- if (xhr.readyState === 4) {
- if (xhr.status === 200) {
- resolve(xhr.responseText);
- } else {
- reject(xhr.responseText);
- }
- }
- }
- });
- }
- ajaxPromise('http://www.baidu.com')
- .then((value) => {
- console.log(value);
- })
- .catch((err) => {
- console.error(err);
- });
6.promise的链式调用
- 每次调用返回的都是一个新的Promise实例
- 链式调用的参数通过返回值传递
then
可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个Promise
对象
- readFile('1.txt').then(function (data) {
- console.log(data);
- return data;
- }).then(function (data) {
- console.log(data);
- return readFile(data);
- }).then(function (data) {
- console.log(data);
- }).catch(function(err){
- console.log(err);
- });
7.promise API
7.1 Promise.all
- 参数:接受一个数组,数组内都是
Promise
实例 - 返回值:返回一个
Promise
实例,这个Promise
实例的状态转移取决于参数的Promise
实例的状态变化。当参数中所有的实例都处于resolve
状态时,返回的Promise
实例会变为resolve
状态。如果参数中任意一个实例处于reject
状态,返回的Promise
实例变为reject
状态。- Promise.all([p1, p2]).then(function (result) {
- console.log(result); // [ '2.txt', '2' ]
- });
不管两个promise谁先完成,Promise.all 方法会按照数组里面的顺序将结果返回
- Promise.all([p1, p2]).then(function (result) {
7.2 Promise.race
- 参数:接受一个数组,数组内都是
Promise
实例 - 返回值:返回一个
Promise
实例,这个Promise
实例的状态转移取决于参数的Promise
实例的状态变化。当参数中任何一个实例处于resolve
状态时,返回的Promise
实例会变为resolve
状态。如果参数中任意一个实例处于reject
状态,返回的Promise
实例变为reject
状态。- Promise.race([p1, p2]).then(function (result) {
- console.log(result); // [ '2.txt', '2' ]
- });
7.3 Promise.resolve
返回一个
Promise
实例,这个实例处于resolve
状态。 - Promise.race([p1, p2]).then(function (result) {
根据传入的参数不同有不同的功能:
- 值(对象、数组、字符串等):作为
resolve
传递出去的值 Promise
实例:原封不动返回
7.4 Promise.reject
返回一个Promise
实例,这个实例处于reject
状态。
- 参数一般就是抛出的错误信息。
8. q
Q是一个在Javascript中实现promise的模块
8.1 q的基本用法
- var Q = require('q');
- var fs = require('fs');
- function read(filename) {
- var deferred = Q.defer();
- fs.readFile(filename,'utf8', function (err, data) {
- if(err){
- deferred.reject(err);
- }else{
- deferred.resolve(data);
- }
- });
- return deferred.promise;
- }
- read('1.txt1').then(function(data){
- console.log(data);
- },function(error){
- console.error(error);
- });
8.2 q的简单实现
- module.exports = {
- defer(){
- var _success,_error;
- return {
- resolve(data){
- _success(data);
- },
- reject(err){
- _error(err);
- },
- promise:{
- then(success,error){
- _success = success;
- _error = error;
- }
- }
- }
- }
- }
8.3 q的实现
- var defer = function () {
- var pending = [], value;
- return {
- resolve: function (_value) {
- if (pending) {
- value = _value;
- for (var i = 0, ii = pending.length; i < ii; i++) {
- var callback = pending[i];
- callback(value);
- }
- pending = undefined;
- }
- },
- promise: {
- then: function (callback) {
- if (pending) {
- pending.push(callback);
- } else {
- callback(value);
- }
- }
- }
- };
- };
9. bluebird
实现 promise 标准的库是功能最全,速度最快的一个库
9.1 bluebird经典使用
- var Promise = require('./bluebird');
- var readFile = Promise.promisify(require("fs").readFile);
- readFile("1.txt", "utf8").then(function(contents) {
- console.log(contents);
- })
- var fs = Promise.promisifyAll(require("fs"));
- fs.readFileAsync("1.txt", "utf8").then(function (contents) {
- console.log(contents);
- })
9.2 bluebird简单实现
- module.exports = {
- promisify(fn){
- return function () {
- var args = Array.from(arguments);
- return new Promise(function (resolve, reject) {
- fn.apply(null, args.concat(function (err) {
- if (err) {
- reject(err);
- } else {
- resolve(arguments[1])
- }
- }));
- })
- }
- },
- promisifyAll(obj){
- for(var attr in obj){
- if(obj.hasOwnProperty(attr) && typeof obj[attr] =='function'){
- obj[attr+'Async'] = this.promisify(obj[attr]);
- }
- }
- return obj;
- }
- }
10. 动画
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>move</title>
- <style>
- .square{
- width:40px;
- height:40px;
- border-radius: 50%;
- }
- .square1{
- background-color: red;
- }
- .square2{
- background-color: yellow;
- }
- .square3{
- background-color: blue;
- }
- </style>
- </head>
- <body>
- <div class="square square1" style="margin-left: 0"></div>
- <div class="square square2" style="margin-left: 0"></div>
- <div class="square square3" style="margin-left: 0"></div>
- </body>
- <script>
- var square1 = document.querySelector('.square1');
- var square2 = document.querySelector('.square2');
- var square3 = document.querySelector('.square3');
- /*function move(element,target,resolve){
- let timer = setInterval(function(){
- var marginLeft = parseInt(element.style.marginLeft, 10);
- if(marginLeft == target){
- resolve();
- }else{
- element.style.marginLeft = ++marginLeft+'px';
- }
- },13);
- }*/
- function move(element,target,resolve){
- let current = 0;
- let timer = setInterval(function(){
- element.style.transform=`translateX(${++current}px)`;
- if(current>target){
- clearInterval(timer);
- resolve();
- };
- },13);
- }
- function animate(element,target){
- return new Promise(function(resolve,reject){
- move(element,target,resolve);
- });
- }
- animate(square1,100)
- .then(function(){
- return animate(square2,100);
- })
- .then(function(){
- return animate(square3,100);
- });
- </script>
- </html>
11. co
11.1 co初体验
- let fs = require('fs');
- function getNumber(){
- return new Promise(function (resolve,reject) {
- setTimeout(function(){
- let number = Math.random();
- if(number >.5){
- resolve(number);
- }else{
- reject('数字太小');
- }
- },1000);
- });
- }
- function *read(){
- let a = yield getNumber();
- console.log(a);
- let b = yield 'b';
- console.log(b);
- let c = yield getNumber();
- console.log(c);
- }
- function co(gen){
- return new Promise(function(resolve,reject){
- let g = gen();
- function next(lastValue){
- let {done,value} = g.next(lastValue);
- if(done){
- resolve(lastValue);
- }else{
- if(value instanceof Promise){
- value.then(next,function(val){
- reject(val);
- });
- }else{
- next(value);
- }
- }
- }
- next();
- });
- }
- co(read).then(function(data){
- console.log(data);
- },function(reason){
- console.log(reason);
- });
11.2 co连续读文件
- let fs = require('fs');
- function readFile(filename){
- return new Promise(function (resolve,reject) {
- fs.readFile(filename,'utf8',function(err,data){
- if(err)
- reject(err);
- else
- resolve(data);
- })
- });
- }
- function *read(){
- let a = yield readFile('./1.txt');
- console.log(a);
- let b = yield readFile('./2.txt');
- console.log(b);
- }
- function co(gen){
- let g = gen();
- function next(val){
- let {done,value} = g.next(val);
- if(!done){
- value.then(next);
- }
- }
- next();
- }
12. Promise/A+完整实现
- function Promise(executor) {
- let self = this;
- self.status = "pending";
- self.value = undefined;
- self.onResolvedCallbacks = [];
- self.onRejectedCallbacks = [];
- function resolve(value) {
- if (value instanceof Promise) {
- return value.then(resolve, reject)
- }
- setTimeout(function () { // 异步执行所有的回调函数
- if (self.status == 'pending') {
- self.value = value;
- self.status = 'resolved';
- self.onResolvedCallbacks.forEach(item => item(value));
- }
- });
- }
- function reject(value) {
- setTimeout(function () {
- if (self.status == 'pending') {
- self.value = value;
- self.status = 'rejected';
- self.onRejectedCallbacks.forEach(item => item(value));
- }
- });
- }
- try {
- executor(resolve, reject);
- } catch (e) {
- reject(e);
- }
- }
- function resolvePromise(promise2, x, resolve, reject) {
- if (promise2 === x) {
- return reject(new TypeError('循环引用'));
- }
- let then, called;
- if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {
- try {
- then = x.then;
- if (typeof then == 'function') {
- then.call(x, function (y) {
- if (called)return;
- called = true;
- resolvePromise(promise2, y, resolve, reject);
- }, function (r) {
- if (called)return;
- called = true;
- reject(r);
- });
- } else {
- resolve(x);
- }
- } catch (e) {
- if (called)return;
- called = true;
- reject(e);
- }
- } else {
- resolve(x);
- }
- }
- Promise.prototype.then = function (onFulfilled, onRejected) {
- let self = this;
- onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : function (value) {
- return value
- };
- onRejected = typeof onRejected == 'function' ? onRejected : function (value) {
- throw value
- };
- let promise2;
- if (self.status == 'resolved') {
- promise2 = new Promise(function (resolve, reject) {
- setTimeout(function () {
- try {
- let x = onFulfilled(self.value);
- resolvePromise(promise2, x, resolve, reject);
- } catch (e) {
- reject(e);
- }
- });
- });
- }
- if (self.status == 'rejected') {
- promise2 = new Promise(function (resolve, reject) {
- setTimeout(function () {
- try {
- let x = onRejected(self.value);
- resolvePromise(promise2, x, resolve, reject);
- } catch (e) {
- reject(e);
- }
- });
- });
- }
- if (self.status == 'pending') {
- promise2 = new Promise(function (resolve, reject) {
- self.onResolvedCallbacks.push(function (value) {
- try {
- let x = onFulfilled(value);
- resolvePromise(promise2, x, resolve, reject);
- } catch (e) {
- reject(e);
- }
- });
- self.onRejectedCallbacks.push(function (value) {
- try {
- let x = onRejected(value);
- resolvePromise(promise2, x, resolve, reject);
- } catch (e) {
- reject(e);
- }
- });
- });
- }
- return promise2;
- }
- Promise.prototype.catch = function (onRejected) {
- return this.then(null, onRejected);
- }
- Promise.all = function (promises) {
- return new Promise(function (resolve, reject) {
- let result = [];
- let count = 0;
- for (let i = 0; i < promises.length; i++) {
- promises[i].then(function (data) {
- result[i] = data;
- if (++count == promises.length) {
- resolve(result);
- }
- }, function (err) {
- reject(err);
- });
- }
- });
- }
- Promise.deferred = Promise.defer = function () {
- var defer = {};
- defer.promise = new Promise(function (resolve, reject) {
- defer.resolve = resolve;
- defer.reject = reject;
- })
- return defer;
- }
- /**
- * npm i -g promises-aplus-tests
- * promises-aplus-tests Promise.js
- */
- try {
- module.exports = Promise
- } catch (e) {
- }
13. 资源
关于Promise的详细总结的更多相关文章
- 关于promise的详细讲解
到处是回调函数,代码非常臃肿难看, Promise 主要用来解决这种编程方式, 将某些代码封装于内部. Promise 直译为"承诺",但一般直接称为 Promise; 代码的可读 ...
- 一道关于Promise应用的面试题
题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次:如何让三个灯不断交替重复亮灯?(用Promse实现) 三个亮灯函数已经存在: function red(){ console.log('red') ...
- 介绍axios和promise
今天小编为大家带来 axios 和promise的详细讲解,包含 axios的使用方法 多种写法,封装 以及 promise的详细讲解,项目中如何运用等,会一一的为大家讲解清楚. 一.axios的介绍 ...
- Promise、Generator、Async有什么区别?
前言 我们知道Promise与Async/await函数都是用来解决JavaScript中的异步问题的,从最开始的回调函数处理异步,到Promise处理异步,到Generator处理异步,再到Asyn ...
- [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 ...
- angularjs和ajax的结合使用 (三)
转眼九月份了,忙忙碌碌 发现今年还没开过张,写一篇吧. 15年在空闲时就倒腾过angularjs那玩意儿 ,觉得还是挺好的,李金龙那厚厚的一本书,只不过没有系统化应用.最主要的是原来有一个东西没有用到 ...
- Vue 入门之 Vuex 实战
Vue 入门之 Vuex 实战 引言 Vue 组件化做的确实非常彻底,它独有的 vue 单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其 Vue 组件设计的就 ...
- redux基础(1)
redux ps:每个案例都是接着上一个案例写的 主要以案例讲解如何使用,具体概念请参考如下: 基本概念参考1 基本概念参考2 案例源码戳这里 一.Store.Action.Reducer简介 Sto ...
- async/await的使用以及注意事项
使用 async / await, 搭配 promise, 可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性. 本文介绍 async / await 的基本用法和一些注意事项. a ...
随机推荐
- C# MVC js 跨域
js 跨域: 第一种解决方案(服务端解决跨域问题): 跨域是浏览器的一种安全策略,是浏览器自身做的限制,不允许用户访问不同域名或端口或协议的网站数据. 只有域名(主域名[一级域名]和二级域名).端口号 ...
- TortoiseSvn介绍 客户端
转载自:http://www.cnblogs.com/lyhabc/articles/2482381.html TortoiseSvn 是 Subversion 版本控制系统的一个免费开源客户端,可以 ...
- POJ Oulipo KMP 模板题
http://poj.org/problem?id=3461 Oulipo Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4 ...
- linux下支持托盘的邮件客户端Sylpheed
在网上搜索了很多客户端想支持系统托盘,发现一个很不错的邮件客户端Sylpheed.设置方式和foxmail很像,最为重要的是支持系统托盘,很方便,默认没有开启,简单设置下:配置->通用首选项-& ...
- U-BOOT概述及源码分析(一)
嵌入式Linux系统从软件角度通常可以分为以下4个层次: 引导加载程序 | Linux内核 | 文件系统 | 用户应用程序 嵌入式Linux系统中典型分区结构: 正常启动过程中,Bootloader首 ...
- SpringBoot 静态资源 加载位置
1.配置自定义拦截器 /** * Copyright (C), 2017-2018, XXX有限公司 * FileName: WebConfig * Author: 丶Zh1Guo * Date: 2 ...
- Logback自定义日志输出内容
场景 一般情况下,日志打印的内容都是根据配置文件中配置的pattern格式指定好的.在我们调用logger.info(), logger.debug()等日志打印方法时,打印的内容格式与配置文件中的p ...
- SPSS提示“列表中不同意存在字符串变量”的解决方法
今天用SPSS对一些数据进行主成分分析,SPSS 19.0进行主成分分析的方法是:分析--降维--因子分析,可是当导入一些变量的时候.就会弹出窗体说"列表中不同意存在字符串变量", ...
- 如何覆盖GCE的DHCP MTU选项
如何覆盖GCE的DHCP MTU选项 在GCE上托管的Linux IPSec隧道不能打开谷歌,这与MTU有关.谷歌管理员认为"改变这个值是一件困难的事情"https://cl ...
- jQuery11 data() : 数据缓存
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...