在JavaScript中,异步操作非常多见,然而在Promise之前,我们是在类似以下的做法中处理多重异步回调,每一层里都要调另一个异步函数,形成了所谓的“回调地狱”, Promis是为了解决回调地狱的方案,是一种链式操作。

什么是Promise?

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

​ ———《ES6入门》阮一峰

《你不知道的js(下卷)》指出:Promise不是对回调的替代,而是在回调代码与将要执行这个任务的异步代码之间提供一种可靠的中间机制来管理回调。

我的理解:

Promise是用来解决写多重回调函数实现异步操作造成代码混乱、不易维护的问题,是一种管理回调代码与执行这个任务的异步代码的中间机制。

很大一部分熟悉jQuery的朋友会说Promise和Deferred有什么区别?其实,Deferred包含了Promise在内。

Promise三个状态

pending(进行中)
fulfilled(已成功)
rejected(已失败)

1、pending->fulfilled

2、pending->rejected

Promise基本用法

Promise的方法

Promise.prototype.then()

它的作用是为 Promise 实例添加状态改变时的回调函数。

Promise.prototype.catch()

.then(null, rejection)的别名,用于指定发生错误时的回调函数。

Promise.all()

用于将多个 Promise 实例,包装成一个新的 Promise 实例

Promise.race()

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Promise.race方法的参数与Promise.all方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。

下面是一个例子,如果指定时间内没有获得结果,就将 Promise 的状态变为reject,否则变为resolve。

const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]); p
.then(console.log)
.catch(console.error);

上面代码中,如果 5 秒之内fetch方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数。

Promise.resolve()

Promise.reject()

Promise.done()

Promise.finally()

方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

Promise的应用

Promise之前处理

//以jQuery为例
// Get html
$.get('/test', function(html) { // Get json data
$.getJSON('/api/test.json', function(json) { // Get the JS
$.getScript('/assets/test.js', function() { // display result
$('.result').text(json.result); // Add html to page
$('body').append(html); }); });

现在使用Promise

先封装一个生产Promise的函数

//先封装一个生产Promise的函数
let promise = function() {
return new Promise((reslove, reject)=>{
$.ajax({
url: 'http: //happymmall.com/user/get_user_info.do',
dataType: 'json',
type: 'get',
success(res){
reslove(res);
},
error(err){
reject(err);
}
})
})
}

然后于将多个 Promise 实例,包装成一个新的 Promise 实例,用then方法进行异步操作管理。

let p1 = new promise();
let p2 = new promise();
Promise.all([p1, p2]).then((result) => {
let [p1, p2] = result;
console.log(p1, p2);
}).catch((err) => {
console.log(err);
});

怎么实现一个Promise polyfill

项目的地址:promise

promiseES6

var Promise = require('../src/promiseES6.js');

Promise.all([
$.ajax({url: './data/1.txt', dataType: 'json'}),
$.ajax({url: './data/2.txt', dataType: 'json'})
]).then((result) => {
let [p1, p2] = result;
console.log(p1, p2);
}).catch((err) => {
console.log(err);
});
promise
var Promise = new Promise((resolve, reject)=>{
setTimeout(resolve, 100, 'foo');
});
Promise.all([
$.ajax({url: './data/1.txt', dataType: 'json'}),
$.ajax({url: './data/2.txt', dataType: 'json'})
]).then((result) => {
let [p1, p2] = result;
console.log(p1, p2);
}).catch((err) => {
console.log(err);
});

测试Promise

测试代码
// 目前是通过他测试 他会测试一个对象
// 语法糖
Promise.defer = Promise.deferred = function () {
let dfd = {}
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
测试
git clone https://github.com/Zenquan/promise.git
cd promise
npm install
promises-aplus-tests promiseES6.js

参考:

Promise 对象

Promise的那些事儿的更多相关文章

  1. ES6知识总结

    ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了.它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应 ...

  2. angular2系列教程(七)Injectable、Promise、Interface、使用服务

    今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我 ...

  3. 细说Promise

    一.前言 JavaScript是单线程的,固,一次只能执行一个任务,当有一个任务耗时很长时,后面的任务就必须等待.那么,有什么办法,可以解决这类问题呢?(抛开WebWorker不谈),那就是让代码异步 ...

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

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

  5. promise知识点汇总

    Promise对象被写进ES6的规范当中,提供的是另外一种更加友好的对于异步编程的解决方案,在这之前大多使用的是回调函数和事件来实现异步编程. 怎么来理解Promise对象呢?对于这个ES6新加入的小 ...

  6. ArcGIS API for JavaScript 4.2学习笔记[7] 鹰眼(缩略图的实现及异步处理、Promise、回调函数、监听的笔记)

    文前说明:关于style就是页面的css暂时不做评论,因为官方给的例子的样式实在太简单了,照抄阅读即可. 这篇文章有着大量AJS 4.x版本添加的内容,如监听watch.Promise对象.回调函数. ...

  7. 一篇文章彻底搞懂es6 Promise

    前言 Promise,用于解决回调地狱带来的问题,将异步操作以同步的操作编程表达出来,避免了层层嵌套的回调函数. 既然是用来解决回调地狱的问题,那首先来看下什么是回调地狱 var sayhello = ...

  8. ES5和ES6那些你必须知道的事儿(三)

    ES5和ES6那些你必须知道的事儿 ES6新增的东西 一.块级作用域:关键字let,常量const let与var的区别: a.不会进行变量声明提升 b.变量不允许被重复定义 c.变量不允许被删除 d ...

  9. util.promisify 的那些事儿

    util.promisify是在node.js 8.x版本中新增的一个工具,用于将老式的Error first callback转换为Promise对象,让老项目改造变得更为轻松. 在官方推出这个工具 ...

随机推荐

  1. 利用kibana插件对Elasticsearch进行批量操作

    #############批量获取################# #获取所有数据 GET _mget { "docs": [ {"_index":" ...

  2. 第九篇 蓝图 blueprint

    在Flask中的蓝图 blueprint 的作用就是将 功能 与 主服务 分开 比如说,你有一个客户管理系统,最开始的时候,只有一个查看客户列表的功能,后来你又加入了一个添加客户的功能(add_use ...

  3. Spark环境搭建(一)-----------HDFS分布式文件系统搭建

    下载的压缩文件放在~/software/    解压安装在~/app/ 一:分布式文件系统搭建HDFS 1,下载Hadoop HDFS环境搭建    使用版本:hadoop-2.6.0-cdh5.7. ...

  4. 201771010126 王燕《面向对象程序设计(Java)》第七周实验总结

    实验七 继承附加实验 实验时间 2018-10-11 1.实验目的与要求 (1)进一步理解4个成员访问权限修饰符的用途: private--私有域或私有方法:只能在定义它的类中使用 public--公 ...

  5. sql的基础用法

    # sql 对大小写不敏感 # 查询表中的所有信息 select * from `Customers`; # 查询指定字段 CustomerName,Country select CustomerNa ...

  6. swust oj 971

    统计利用先序遍历创建的二叉树的深度 10000(ms) 10000(kb) 3331 / 8436 利用先序递归遍历算法创建二叉树并计算该二叉树的深度.先序递归遍历建立二叉树的方法为:按照先序递归遍历 ...

  7. Spring Session event事件分析

    1. org.apache.catalina.session.StandardSession 这是servlet-api jar包中的一个类.是session接口的标准实现.当session创建的时候 ...

  8. 报文分析3、ICMP协议的头结构

    ICMP协议的头结构 类型(8位) 代码(8位) 校验和(8位) 类型或者代码   (1)类型:一个8位类型字段,表示ICMP数据包类型. (2)代码:一个8位代码域,表示指定类型中的一个功能.如果一 ...

  9. ETL数据采集方法

    1.触发器方式 触发器方式是普遍采取的一种增量抽取机制.该方式是根据抽取要求,在要被抽取的源表上建立插入.修改.删除3个触发器,每当源表中的数据发生变化,就被相应的触发器将变化的数据写入一个增量日志表 ...

  10. vue-cli 创建项目失败

    vue-cli 创建一个vue项目报错 npm code 404. 尝试解决方法都有,我是第3种方法生效 更新npm 重新安装nodejs vue-cli@3.0.1 在创建项目的时候,不能开启其他v ...