promise 是 es6 中新增的一个对象 是异步编程的解决方案, 主要解决异步编程中多个回调函数的使用问题
在实际开发过程中, 我们可能遇到不止一个异步操作, 每个异步操作都会有一个回调函数; 那么有没有可能出现这样一种情况: 本次异步操作的结果需要与下次异步操作关联起来; 换一种说法就是本次异步操作当成下次异步操作的执行条件; 这个当然是有可能存在的.
其实要实现上面的情况其实也很简单, 那就是利用嵌套的关系; 这样程序就会从最外层的代码开始执行; 执行完成后才会执行内层函数; 然后再执行完成后再执行最内层函数, 这样一层层的直到最内层层程序执行完毕, 这样就可以解决上述问题.
- setTimeout(function(){
- console.log('第一层');
- setTimeout(function(){
- console.log('第二层');
- setTimeout(function(){
- console.log('第三层');
- },1000)
- },1000)
- },1000)
但是, 如果逻辑复杂或者嵌套过多的话, 很容易形成回调地狱. 回调地狱是由于糟糕的编码习惯造成的, 不仅会造成代码混乱, 还特别容易出错.
而使用 promise 会将程序变成我们最熟悉的链式执行顺序, 这样既方便书写, 也能很直观的看出结果, 将复杂的回调嵌套变成正常的链式调用
promise 的使用
promise 有三种状态 pending fulfilled rejected
promise 有两种变化过程 pending => fulfiled(成功) pending => rejected(失败)
一旦状态发生改变, 就不会再变化了
- let p1 = new Promise((resolve,reject)=>{
- setTimeout(resolve,3000)
- })
- p1.then(()=>{
- console.log('第一层');
- }).then(()=>{
- console.log('第二层');
- }).then(()=>{
- console.log('第三层');
- })
这样写看似没什么错误, 但是最后的出的结果却是错误的, 因为 Promise 的实例只有一个, 所有状态的改变都会依赖于 p1 的改变而同时改变 . 所以每当状态改变的时候, 返回一个新的 Promise 实例来使状态刷新
- let p1 = new Promise((resolve,reject)=>{
- setTimeout(resolve,3000)
- })
- p1.then(()=>{
- console.log('第一层');
- return new Promise((resolve,rejct)=>{
- setTimeout(resolve,2000)
- })
- }).then(()=>{
- console.log('第二层');
- return new Promise((resolve,rejct)=>{
- setTimeout(resolve,1000)
- })
- }).then(()=>{
- console.log('第三层');
- })
这样就可以实现链式调用了. 但是这样写还会存在问题: 首先是代码量很大; 其次是代码重复很多. 这时候我们就自然而然的想到了封装
- function timeout(time){
- return new Promise((resolve,reject)=>{
- setTimeout(resolve,time);
- })
- }
- timeout(3000).then(()=>{
- console.log('第一层');
- return timeout(2000);
- }).then(()=>{
- console.log('第二层');
- return timeout(1000);
- }).then(()=>{
- console.log('第三层');
- })
promise 的其他方法
3.1 catch 对应失败时候的方法, 与 then 用法类似, 对应失败时候的回调函数
3.2 all() 当所有实例都满足条件后才会去执行后面对应的函数
- function timeout(time){
- return new Promise((resolve,reject)=>{
- setTimeout(resolve,time);
- })
- }
- let p1 = timeout(5000);
- let p2 = timeout(3000);
- let p3 = timeout(1000);
- Promise.all([p1,p2,p3]).then(function(){
- console.log("ceshi");
- })
3.3 race() 某一个实例满足条件后就会执行后面对应的函数
- function timeout(time){
- return new Promise((resolve,reject)=>{
- setTimeout(resolve,time);
- })
- }
- let p1 = timeout(5000);
- let p2 = timeout(3000);
- let p3 = timeout(1000);
- Promise.race([p1,p2,p3]).then(function(){
- console.log("ceshi");
- })
promise 与 Ajax
基于 promise 的 Ajax 函数封装
- function Ajax(url){
- return new Promise(function(resolve,reject){
- if(Windows.XMLHttpRequest){
- var xhr = new XMLHttpRequest();
- }else{
- var xhr = new ActiveXObject("Microsoft.XMLHTTP");
- }
- xhr.open("GET",url,true);
- xhr.send();
- xhr.onreadystatechange = function(){
- if(xhr.readyState == 4){
- if(xhr.status == 200){
- var data = xhr.responseText;
- resolve(data);
- }
- }
- }
- })
- }
来源: http://www.jianshu.com/p/c0726ff521a9