ES6新特性:Javascript中内置的延迟对象Promise
Promise的基本使用:
利用Promise是解决JS异步执行时候回调函数嵌套回调函数的问题, 更简洁地控制函数执行流程;
通过new实例化Promise, 构造函数需要两个参数, 第一个参数为函数执行成功以后执行的函数resolve, 第二个函数为函数执行失败以后执行的函数reject:
new Promise(function(resolve , reject) {
});
通过Promise,我们把回调函数用线性的方式写出来,而不是一层套一层, 这个函数有四层回调;
fn("args", function(a) {
fn1("foo", function(b) {
fn2("bar", function(c) {
fn3("baz", function(d) {
alert("回调成功,获知的内容为:"+a+b+c+d)
})
})
})
})
以上的Demo只有包含成功的回调, 如果失败的回调也算的话, 也就更麻烦了;
如果使用Promise的方式,我们可以改装成线性的代码, 更加符合阅读的习惯,只要在then函数下写逻辑即可;
new Promise(function(resolve , reject) {
resolve();
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
});
这是一个ajax异步获取数据的例子, 我们使用了回调函数;
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
var callback = function(res) {
console.log(res);
};
var ajax = function(url, callback) {
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != || r.status != ) return;
var data = JSON.parse(r.responseText);
callback(data);
};
r.send();
};
//执行请求:
ajax("http://www.filltext.com?rows=10&f={firstName}", callback);
//再做别的事情;
</script>
</body>
</html>
因为ES6内置了Promise, 我们可以把以上的callback改写成promise的方式, 首先ajax函数返回一个Promise对象;
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
var callback = function(res) {
console.log(res);
};
var ajax = function(url) {
return new Promise(function(resolve, reject) {
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != || r.status != ) return;
var data = JSON.parse(r.responseText);
resolve(data);
};
r.send();
})
};
//执行请求:
ajax("http://www.filltext.com?rows=10&f={firstName}").then(function(data) {
callback(data);
});
//再做别的事情;
</script>
</body>
</html>
Promise实例的三种状态:
每一个实例化的Promise都有三个状态;pending(等待) rejected(拒绝) resolved(解决) ,默认的状态为pending,如果执行了resolve(), 那么这个promise的状态会变为resolve,如果执行了reject(), 那么这个promise的状态就会变成rejected, 而且这些状态是不可撤销的,一经更改,不会再变了;
then方法:
promise有一个then方法,then方法接收两个参数, 第一个为函数的成功回调, 第二个为函数的失败回调:
var promise = new Promise(function(resolve , reject) {
resolve(); //执行成功回调;
});
console.log();
promise.then(function(val) {
console.log();
}, function() {
console.log("失败");
});
console.log("");
var promise = new Promise(function(resolve , reject) {
reject();
});
console.log();
promise.then(function(val) {
console.log();
}, function() {
console.log("失败");
});
console.log("");
then方法每一次都是返回不同的Promise实例,then的第一个参数是成功回调, 这个成功回调的参数为: 上一个Promise实例执行resolve方法的参数;
一般来说, then方法会返回当前的promise, 如果在then方法里面return 一个新的Promise实例,那么此时的then返回的就是新的Promise实例, 利用这个特性,就可以实现多层回调;
new Promise(function(resolve , reject) {
resolve();
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
});
不管代码是异步还是同步的, 都可以用Promise的then方法, 同步的代码直接写在then方法第一个参数, 把需要参数通过resolve传给下一个then方法,
如果是异步的代码, 就直接return一个Promise实例:
new Promise(function(resolve , reject) {
resolve();
}).then(function(val) {
console.log(val);
return ;
}).then(function(val) {
console.log(val);
return ;
}).then(function(val) {
console.log(val);
return new Promise(function(resolve,reject) {
//异步操作些这里
resolve();
});
}).then(function(val) {
console.log(val);
return ;
}).then(function(val) {
console.log(val);
});
catch方法:
catch方法和失败回调时一样的, 如果上一个异步函数抛出了错误了, 错误会被捕获, 并执行catch方法或者失败回调;
var promise = new Promise(function(resolve , reject) {
resolve(); //执行成功回调;
});
console.log();
promise.then(function(val) {
console.log("成功");
throw new Error("heheda");
}).catch(function(e) {
console.log(e);
}).then(function() {
console.log("继续执行");
});
Promise中的错误是会一层层传递的, 如果错误没有没有被捕获, 会一直传递给下一个promise对象, 直到被捕获为止, 然后继续往下执行:
new Promise(function(resolve , reject) {
resolve();
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
throw new Error("err");
});
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
return new Promise(function(resolve , reject) {
resolve();
});
}).then(function(val) {
console.log(val);
}).catch(function(err) {
console.log(err);
}).then(function() {
console.log("继续执行")
})
构造函数Promise的四个方法:
构造函数Promise有四个方法, Promise.all, Promise.race, Promise.reject, Promise.resolve:
Promise.all(iterable)
返回一个promise对象,当iterable参数里所有的promise都被解决后,该promise也会被解决
要注意all方法是Promise函数的方法,不是实例的方法, 参数是一个数组, 数组里面全是Promise的实例 :
var p0 = new Promise(function(resolve) {
setTimeout(function() {
resolve()
},);
})
var p1 = new Promise(function(resolve) {
setTimeout(function() {
resolve()
},);
})
var p2 = new Promise(function(resolve) {
setTimeout(function() {
resolve()
},);
})
Promise.all([p0,p1,p2]).then(function(arr) {
console.log(arr)
})
Promise.race(iterable)
当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
Promise.reject(reason)
调用Promise的rejected句柄,并返回这个Promise对象。
Promise.resolve(value)
用成功值value解决一个Promise对象。如果该value为可继续的(thenable,即带有then方法),返回的Promise对象会“跟随”这个value,采用这个value的最终状态;否则的话返回值会用这个value满足(fullfil)返回的Promise对象。
官方的例子:
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="log"></div>
<script>
'use strict';
var promiseCount = ;
function testPromise() {
var thisPromiseCount = ++promiseCount; var log = document.getElementById('log');
log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 开始(同步代码开始)<br/>'); // 我们创建一个新的promise: 然后用'result'字符串解决这个promise (3秒后)
var p1 = new Promise(function (resolve, reject) {
// 解决函数带着解决(resolve)或拒绝(reject)promise的能力被执行
log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise开始(异步代码开始)<br/>'); // 这只是个创建异步解决的示例
window.setTimeout(function () {
// 我们满足(fullfil)了这个promise!
resolve(thisPromiseCount)
}, Math.random() * + );
}); // 定义当promise被满足时应做什么
p1.then(function (val) {
// 输出一段信息和一个值
log.insertAdjacentHTML('beforeend', val + ') Promise被满足了(异步代码结束)<br/>');
}); log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 建立了Promise(同步代码结束)<br/><br/>');
}
testPromise();
</script>
</body>
</html>
既然有了Promise , 我们就可以把封装XMLHttpRequest封装成GET方法, 方便使用:
function get(url) {
// Return a new promise.
return new Promise(function(resolve, reject) {
// Do the usual XHR stuff
var req = new XMLHttpRequest();
req.open('GET', url); req.onload = function() {
// This is called even on 404 etc
// so check the status
if (req.status == ) {
// Resolve the promise with the response text
resolve(req.response);
}
else {
// Otherwise reject with the status text
// which will hopefully be a meaningful error
reject(Error(req.statusText));
}
}; // Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
}; // Make the request
req.send();
});
}
然后使用:
get('story.json').then(function(response) {
console.log("Success!", response);
}, function(error) {
console.error("Failed!", error);
});
假数据的地址可以自己设置, 可以通过控制台请求, 注意跨域的问题;
封装XMLHttpRequest成Promise异步加载图片的案例:https://github.com/mdn/promises-test/blob/gh-pages/index.html
其他:
以上只是Promise的一些基础知识, 还有一些其他的知识点, 因为能力有限不一一介绍了(Promise.resolve的不同参数, 与Generator一起使用, Promise的附加方法, 等等等等);
把Promise的运行流程画出来, 对Promise的理解会好一点, Promise还是比较绕的
浏览器支持情况:
Chrome 32, Opera 1,Firefox 29, Safari 8 ,Microsoft Edge, 这些浏览器以上都默认支持;
参考
Promises/A+ 规范: https://promisesaplus.com/
ES6Promises的polyfill : https://github.com/stefanpenner/es6-promise#readme
html5rocks:http://www.html5rocks.com/en/tutorials/es6/promises/
阮老师:http://es6.ruanyifeng.com/#docs/promise
作者: NONO
出处:http://www.cnblogs.com/diligenceday/
QQ:287101329
微信:18101055830
ES6新特性:Javascript中内置的延迟对象Promise的更多相关文章
- JavaScript中内置对象的一些属性及方法
Javascript对象总结 JS中内置了17个对象,常用的是Array对象.Date对象.正则表达式对象.string对象.Global对象 Array对象中常用方法: Concat():表示把几个 ...
- javascript中内置函数
一.基本函数库 split():用于把一个字符串分割成字符串数组 toUpperCase(): substr(): 长度 length() 拼接(两种) + concat():合并多个字符串,并返回合 ...
- javascript ES6 新特性之 扩展运算符 三个点 ...
对于 ES6 新特性中的 ... 可以简单的理解为下面一句话就可以了: 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中. 作用类似于 Object.assign() ...
- ES6新特性概览
本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...
- ES6新特性以及一些规范
1.let:使变量成为块级变量,类似于C++,java类的变量 b = 2 if (b == 2) { let c = 2; } console.log(c) // 报错,因为c是一个块级变量,只存在 ...
- js中内置有对象
statpot:使用mongo+bootstrap+highcharts做统计报表 最近做了一个统计项目,这个统计项目大致的需求是统计接口的访问速度.客户端会调用一个接口来记录接口的访问情况,我的需求 ...
- 你不知道的JavaScript--Item24 ES6新特性概览
ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...
- 前端入门21-JavaScript的ES6新特性
声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...
- 34.js----JS 开发者必须知道的十个 ES6 新特性
JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...
随机推荐
- scrollview 图片放大 捏合 瓦片地图 相关注意事项
就职文博公司要为博物馆做APP 涉及到瓦片地图的编写 在这里总结一些开发中遇到的问题 (将会不断更新 也是学习阶段) 着急写项目的同学 可以直接看code4上现成的瓦片地图代码:http://www. ...
- Linux系统安装NoSQL(MongoDB和Redis)步骤及问题解决办法
➠更多技术干货请戳:听云博客 如下是我工作中的记录,介绍的是linux系统下NoSQL:MongoDB和Redis的安装过程和遇到的问题以及解决办法: 需要的朋友可以按照如下步骤进行安装,可以快速安装 ...
- iPad编程
1. iPad 现有型号: iPad Pro, iPad Air, iPad mini 均配备Retina显示屏.早期还有iPad 依次对应的坐标系及分辨率: iPad Pro 坐标系:1366 x ...
- UIweib的简单实用
- 使用PhoneGap开启移动开发之旅
移动市场风起云涌,只是好像和悲催的.net程序员隔绝.我们内心中一直期待的Windows Phone终究不能匹及windows, 随着时间的流逝,windows phone越来越像扶不起的阿斗,连微软 ...
- spark streaming 与 kafka 结合使用的一些概念理解
1. createStream会使用 Receiver:而createDirectStream不会,数据会通过driver接收. 2.createStream使用 Receiver 源源不断的接收数据 ...
- 从零自学Hadoop(17):Hive数据导入导出,集群数据迁移下
阅读目录 序 将查询的结果写入文件系统 集群数据迁移一 集群数据迁移二 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephis ...
- 1. 什么是Docker?
##### 一.什么是Dokcer?> Docker是一个开源项目, 诞生于2013年初, 最初是dotCloud公司内部的一个业余项目. 它基于Google公司推出的Go语言实现. 项目后来加 ...
- Linux的概念与体系
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我在这一系列文章中阐述Linux的基本概念.Linux操作系统继承自UNIX.一个 ...
- ELF Format 笔记(十五)—— 符号哈希表
ilocker:关注 Android 安全(新手) QQ: 2597294287 符号哈希表用于支援符号表的访问,能够提高符号搜索速度. 下表用于解释该哈希表的组织,但该格式并不属于 ELF 规范. ...