ES6新特性之 promise
新的ES6中引入了promise的概念,目的是让回调更为优雅。层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用。于是Promise就应运而生。Promise即承诺的意思,new一个Promise就是新建一个承诺。在新建一个承诺的时候你需要做两件事情:
1.指定承诺所需完成的事
2.设置承诺是否实现的标准
下面我们来定义一个承诺:
1.承诺的内容:“获取data.php的数据”,
2.承诺是否实现的评判是:“是否获取data.php的数据 ”
这里我们会用到jQuery.ajax()方法,这会让我们的代码显得简单精炼。
var http = {
get: function(url) {
var promise = new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get',
success: function(data) {
resolve(data);
},
error: function(xhr, statusText) {
reject(statusText);
}
});
});
return promise;
}
};
http.get('data.php').then(function(data) {
document.write(data);
}, function(err) {
document.write(err);
});
这里是获取的data值
/* data.php文件 */
<?php
echo '{"name":"Tom","age":"22"}';
在http请求中,我们定义了一个get方法,在get方法中,我们定义了一个promise的对象,而不是直接直接使用ajax获取到我们想要的数据,在这个get方法,我们最后得到的是一个promise对象,对于这种需要等待的操作,我们采用promise去处理,返回给主线程的是一个promise对象,而不是一个最终的数据,这是延迟程序给主程序的一个承诺,主线程可以根据通过返回的promise对象获取数据或者处理错误。这使得异步处理变得优雅而简单。
在jQuery.ajax()中,我们采用了两个方法来判断是否实现了我们的承诺,它们分别是resove和reject方法,如果如果jQuery.ajax()执行了success,并且返回的data中有数据,那么我们就判定这个承诺已经实现了(fulfilled),则调用resolve方法。如果jQuery.ajax()执行了error,那么我们就判定这个承诺被拒绝了(rejected),则调用reject方法。
那resove和reject这两个方法分别执行了哪些操作呢?这个我们就需要从Promise这个构造函数本身的结构说起。Promise这个构造函数结构大概是下面这样的:
/* 用于描述思维的代码 */
function Promise(executor) {
// 共有三种状态:pending(准备)、fulfilled(完成)、rejected(拒绝)
this.PromiseStatus = 'pending';
// 用于存储返回的数据
this.PromiseValue;
// 完成
var resolve = function(reson) {};
// 拒绝
var reject = function(reson) {};
...
// 开始执行承诺
executor(resolve, reject);
}
Promise.prototype.then = function() {};
Promise.prototype.chain = function() {};
Promise.prototype.catch = function() {};
...
PromiseStatus:用于记录Promise对象的三种状态,这三中状态分别是:
pending:待定状态,Promise对象刚被初始化的状态
fulfilled:完成状态,承诺被完成了的状态
rejected:拒绝状态,承诺完成失败的状态
Promise的初始状态是pending。随后会更具承诺完成的情况更改PromiseStatus的值。
PromiseStatus:用于记录返回的数据或者错误。当承诺完成时,会把返回的数据赋给PromiseStatus。如果承诺执行失败了,那么失败的原因也会赋给此变量。
resolve()和reject():Promise构造函数中有两个闭包的函数resolve()和reject()。在new一个新的Promise的时候会传递一件你需要做的事情(executor)。这个executor是一个函数,在Promise的构造函数中它会被传入两个参数,这两个参数即我们的两个闭包的函数resolve()和reject(),以便你在executor中判定是否完成了你的承诺。
executor(): executor()函数中执行的代码就是子程序需要完成事。在executor()函数内如果调用了resolve(),resolve()则会把Promise对象的状态PromiseStatus修改为fulfilled,把resolve(value)中的value值赋给Promise对象的PromiseValue。然后再依次执行由then()方法构成的回调链中的回调函数。同样,在executor()中调用reject()的过程也是类似的。调用过程如下:
/* 用于描述思维的代码 */
executor(resolve, reject) {
...
resolve(value);
...
}
...
resolve(value) {
PromiseStatus = 'fulfilled';
PromiseValue = value;
...
// 接着调用回调链中的回调函数
}
then(onFulfilled, onRejected):这个方法实际上是把onFulfilled()函数和onRejected()函数添加到Promise对象的回调链中。回调链就像一个由函数组构成的队列,每一组函数都是由至少一个函数构成(onFulfilled() 或者 onRejected() 或者 onFulfilled() 和 onRejected())。当resolve()或者reject()方法执行的时候,回调链中的回调函数会根据PromiseStatus的状态情况而被依次调用。
onFulfilled(value)和onRejected(reason):参数value和reason的实参都是PromiseValue。这里有一点值得注意,如果onFulfilled(value)和onRejected(reason)这两个回调函数中return返回值不是一个Promise的对象,那么这个返回值会被赋给PromiseValue,并在下一个then()的onFulfilled(value)和onRejected(reason)中做为实参使用。但如果这个返回值是一个Promise的对象,那么剩下的由then()构造的回调链会转交给新的Promise对象并完成调用。
有这样一个问题,如果在第一个then()中执行了onRejected(reason)回调函数,并且没有return任何值的时候,那么下一个then()中将会调用onFulfilled(value)方法,而不是onRejected(reason)。因为在执行上一个then()的onRejected(reason)回调函数的时候并没有出现错误或异常,所以PromiseStatus的状态就被更改为fulfilled了。为了避免这个问题,我们可以在onRejected(reson)中返回一个Promise对象并reject()。代码如下,我们要去访问一个并不存在的文件solve.php:
var http = {
get: function(url) {
var promise = new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get',
success: function(data) {
resolve(data);
},
error: function(xhr, statusText) {
reject(statusText);
}
});
});
return promise;
}
};
http.get('solve.php').then(function(data) {
return data;
}, function(err) {
return Promise.reject('Sorry, file not Found.');
}).then(function(data) {
document.write(data);
}, function(err) {
document.write(err);
});
Promise.reject()方法会返回一个被reject()的Promise对象,因此使得我们可以继续走下一个then()中的onRejected(reason)方法。
这个是对于promise的一些终结,参考了道友们的思考,原文链接:http://www.jianshu.com/p/87183851756f
ES6新特性之 promise的更多相关文章
- javascript ES6 新特性之 Promise,ES7 async / await
es6 一经推出,Promise 就一直被大家所关注.那么,为什么 Promise 会被大家这样关注呢?答案很简单,Promise 优化了回调函数的用法,让原本需要纵向一层一层嵌套的回调函数实现了横向 ...
- ES6新特性概览
本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...
- 必须掌握的ES6新特性
ES6(ECMAScript2015)的出现,让前端开发者收到一份惊喜,它简洁的新语法.强大的新特性,带给我们更便捷和顺畅的编码体验,赞! 以下是ES6排名前十的最佳特性列表(排名不分先后): 1.D ...
- 你不知道的JavaScript--Item24 ES6新特性概览
ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...
- 前端入门21-JavaScript的ES6新特性
声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...
- 34.js----JS 开发者必须知道的十个 ES6 新特性
JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...
- ES6新特性概览1
本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...
- 前端学习笔记 --ES6新特性
前言 这篇博客是我在b站进行学习es6课程时的笔记总结与补充. 此处贴出up主的教程视频地址:深入解读ES6系列(全18讲) 1.ES6学习之路 1.1 ES6新特性 1. 变量 2. 函数 3. 数 ...
- ES6新特性之模板字符串
ES6新特性概览 http://www.cnblogs.com/Wayou/p/es6_new_features.html 深入浅出ES6(四):模板字符串 http://www.infoq.c ...
随机推荐
- Lambda表达式详解
前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能之一 ...
- IDE-Sublime【3】-配置Node.js开发环境
一.下载Nodejs插件,下载地址为https://github.com/tanepiper/SublimeText-Nodejs,解压到当前文件夹,改名为Nodejs 二.打开Sublime Tex ...
- IE浏览器下一些图片无法显示的(在其他非ie浏览器能够显示)解决办法
因为要完成本学期老师布置得网页作业,做完的时候进行网页的兼容性测试,chrome和360都没有问题. ie下却有两个图片无法显示. 一般这种情况代码是没有什么问题的,一般是图片本身的问题, 当我用Ps ...
- webdav不识别软链接?解决办法?
webdav不识别软链接?解决办法? 在使用webdav实现公网存储共享的时候,发现webdav并不支持软链接的共享,如下源代码可以100%确定这个问题 /* ### for now, only pr ...
- 转载:Chrome调试折腾记_(1)调试控制中心快捷键详解!!!
转载:http://blog.csdn.net/crper/article/details/48098625 大多浏览器的调试功能的启用快捷键都一致…按下F12;还是熟悉的味道; 或者直接 Ctrl ...
- Jquery垂直下拉二级菜单
自己做了一个基于Jquery 的垂直下拉二级菜单功能,直接看图: Html的代码如下: <!DOCTYPE html> <html> <head> <meta ...
- router路由去掉#!的踩坑记
项目中在研究去掉router#!的过程中的踩坑过程.
- SEO网站内链匹配工具
最近在弄一个网站,想体验一下SEO方面的工作. 虽然自己是从事.NET方面工作的,但时间有限,所以用了DEDECMS作为网站的程序. 而SEO里面最重要的一项就是内链.但DEDECMS没有直接的内链匹 ...
- css制作对话框
当你发现好多图都能用css画出来的时候,你就会觉得css很有魅力了.//我是这么觉得的,先不考虑什么兼容问题 像漫画里出现的对话框,往往都是一个对话框然后就加入一个箭头指向说话的那一方,来表示这个内容 ...
- Redis 的安装与使用(linux)
官方教程:http://www.redis.io/download 1.下载Redis # wget http://download.redis.io/releases/redis-3.0.4.tar ...