浏览器的控制台真是个好东西,啥都能干:

这就是Promise,能看出来啥?

  1、是个构造函数,可以new实例。

  2、自身有一些方法:all、race、reject、resolve...

  3、原型上有catch、then...

玩玩吧

Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。Promise是有状态的:resolve时,Promise的状态为fullfiled,reject时,Promise的状态为rejected。

<script>

    var p = new Promise(function(resolve, reject){
//模拟异步操作
setTimeout(function(){
console.log('执行完成');
resolve('成功之后返回的数据');
}, 2000);
}); </script>

运行代码

在上面的代码中,我们执行了一个异步操作,也就是setTimeout,2秒后,输出“执行完成”,并且调用resolve方法。

有没有感觉怪怪的,是的,我只是new了一个Promise对象,传进去的函数就已经执行了。为了方法执行可控且合理,我们把它放在一个方法里,调用的时候才执行:

<script>
function runAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('执行成功之后的数据');
}, 2000);
});
return p;
} runAsync();
</script>

运行代码

我们说了Promise是一个包含了执行状态(成功或失败)的对象,所以我们在上边的方法中返回了这个对象,以便我们接下来对相应结果进行处理。怎么处理呢?这里就要用到then,catch方法:

<script>
function runAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('执行成功之后的数据');
}, 2000);
});
return p;
} runAsync().then(function(data){
console.log(data);
//后面可以用传过来的数据做些其他操作
//......
});
</script>

运行代码

在runAsync()的返回上直接调用then方法,then接收一个参数,是函数,并且会拿到我们在runAsync中调用resolve时传的的参数。运行这段代码,会在2秒后输出“执行完成”,紧接着输出“执行成功之后的数据”。

和普通回调函数的区别

我们平时用的回调函数,其执行过程是,主函数执行(异步请求成功)之后,回调函数就立即执行了。看一下

<script>
function runAsync(callback){
setTimeout(function(){
console.log('执行完成');
callback('回调函数执行');
}, 2000);
} runAsync(function(data){
console.log(data);
});
</script>

运行代码

所以普通回调的特点就是,异步请求成功,就会立即执行。而Promise对象的不同,就是在异步请求之后,把请求之后的状态(成功或失败)和数据赋给了返回的Promise对象。在我们需要对异步请求的结果进行处理的时候,我们只要单独的对这个Promise对象进行操作就行了。

第二个区别就是,普通的回调函数如果也是一个异步请求,就会出现异步请求嵌套,如果层级比较多就会显得很臃肿。虽然我们可以采用命名函数进行优化,但是涉及到闭包和传参,总是很复杂。Promise就解决了这个问题,它能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数,就是Promise.then().then().then().......

来点干货,实现一下红绿灯的效果:

<style type="text/css">
.light{list-style: none;}
.light li{width: 20px;height: 20px;border: 1px solid #F1F1F1;border-radius: 50%;float: left;margin-right: 2px;}
.light li:last-child{position: relative;top: 20px;left: -36px;}
.light-red{background: #F00;}
.light-blue{background: #0F0;}
.light-yellow{background: #FF0;}
.light-default{background: #FFF;}
</style>
<ul class="light">
<li class="light-red light-default"></li>
<li class="light-yellow light-default"></li>
<li class="light-blue light-default"></li>
</ul>
<script type="text/javascript">
//Promise对象,resolve返回数据
function turnLight(n){
var p = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(n);
},300);
});
return p;
} function runLight(){
   //执行
turnLight(0)
.then(function(n){
toggleClass(n);
return turnLight(n+1);
})
.then(function(n){
toggleClass(n);
return turnLight(n+1);
})
.then(function(n){
toggleClass(n);
});
} clearInterval(timer);
var timer = setInterval(runLight,900); function toggleClass(n){
$(".light li").eq(n).removeClass("light-default").siblings().addClass("light-default");
}
</script>

运行代码

Promise对象还有一些其他的方法:

reject方法

resove方法是在异步请求成功之后返回数据的,reject方法一般是在请求失败之后处理数据的。

<script>
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
return p;
} getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
},function(reason, data){
console.log('rejected');
console.log(reason);
});
</script>

运行代码

这里模拟了异步请求的成功和失败。当随机数小于等于5,认为是成功,大于5认为是失败的。then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。

catch方法

catch方法就是把then方法的第二个回调单独列出来,对应reject

<script>
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
return p;
} getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
       console.log(dataaa);
})
.catch(function(reason, data){
console.log('rejected');
console.log(reason);
});
</script>

运行代码

在then里多写一个输出,打印dataaa,一般的方法到这里肯定会报错,但是在这里,不会报错,而是继续进入catch方法执行,并且在catch里输出报错信息。这与try/catch语句有相同的功能。

all方法

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。

<script>
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
resolve(num);
}, 2000);
});
return p;
} Promise.all([getNumber(), getNumber(), getNumber()]).then(function(results){
  console.log(results);//[7, 5, 8]
  });
</script>

运行代码

用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。

race方法

和all方法相对应,race方法则是有一个操作执行完,就执行回调

<script>
function getNumber(n){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
console.log("第"+n+"个执行完,输出"+num);
resolve(num);
}, 2000);
});
return p;
} Promise.race([getNumber(1), getNumber(2), getNumber(3)]).then(function(results){
  console.log(results);    
  }); //第1个执行完,输出3
//3
//第2个执行完,输出1
//第3个执行完,输出4
</script>

运行代码

然而第一个执行完之后,后两个并没有停止,而是继续执行,执行了打印。只是没再执行resolve。race方法的作用可以进行加载超时的控制:

<script>
//请求某个图片资源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx';
});
return p;
} //延时函数,用于给请求计时
function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片请求超时');
}, 5000);
});
return p;
} Promise
.race([requestImg(), timeout()])
.then(function(results){
console.log(results);
})
.catch(function(reason){
console.log(reason);
});
</script>

运行代码

代码很简单,试一下吧~~

理解ES6——Promise的更多相关文章

  1. ES6 Promise的resolved深入理解

    Promise的概念在ES6标准推出来之前已经深入人心,很多框架和第三方库都有类似的实现.但在深入理解ES6的Promise对象的时候,受之前经验的影响,很多概念给人似是而非的感觉,其中有一个特别明显 ...

  2. 深入理解ES6里的promise

    一.ES6 Promise是什么? 复杂的概念先不讲,我们先简单粗暴地把Promise用一下,有个直观感受.那么第一个问题来了,Promise是什么呢?是一个类?对象?数组?函数? 别猜了,直接打印出 ...

  3. 通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise

    Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同.不过它们的作用可以简单的用两句话来描述 Deffered 触发 resolve ...

  4. ES6 Promise 状态解惑

    Promise的概念在ES6标准推出来之前已经深入人心,很多框架和第三方库都有类似的实现.但在深入理解ES6的Promise对象的时候,受之前经验的影响,很多概念给人似是而非的感觉,其中有一个特别明显 ...

  5. Es6 Promise 用法详解

     Promise是什么??    打印出来看看  console.dir(Promise) 这么一看就明白了,Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方 ...

  6. ES6 Promise 异步操作

    最近越来越喜欢与大家进行资源分享了,并且及时的同步到自己的园子内,为什么呢? 一.小插曲(气氛搞起) 在上个月末,由于领导的高度重视(haha,这个高度是有多高呢,185就好了),走进了公司骨干员工的 ...

  7. 解析ES6 Promise

    ES6 Promise 概念之类的,大概读者都应该有所知道,接下来我们直入终点. 先让我们来看看什么是Promise吧,他是一个object,类,arry,function? 首先,学习它的时候应该讲 ...

  8. 浅谈es6 promise

    本文是借鉴于ac黄的博客. 接触es6也有几个月了,貌似没有系统的去学习过它,总是用到什么,查查什么.今天就说下es6中的promise对象. 先说说promise解决了什么问题? 写前端的同学都经常 ...

  9. ES6 Promise(2)

    Promise的兴起,是因为异步方法调用中,往往会出现回调函数一环扣一环的情况.这种情况导致了回调金字塔的出现.不仅代码写起来费劲不美观,而且问题复杂的时候,阅读代码的人也难以理解. db.save( ...

随机推荐

  1. Visual Studio Code 配置C++环境

    Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮.智能代码补全.自定义热键.括号匹配.代码片段. ...

  2. mysql查看表结构2种方式对比

    1.desc t_bookType; 2.show create table t_bookType; 相信大部分人还是喜欢第一种查看表结构方式.

  3. Spark Structured Streaming框架(2)之数据输入源详解

    Spark Structured Streaming目前的2.1.0版本只支持输入源:File.kafka和socket. 1. Socket Socket方式是最简单的数据输入源,如Quick ex ...

  4. windows 计划任务执行python脚本

    1.  查找并打开Windows计划任务 2. 创建任务 3. 输入名称 4. 通过触发器设置运行时间或周期 5. 通过操作,设置运行的脚本 a. 操作选择'启动程序' b. 程序或脚本选择 pyth ...

  5. 多线程编程学习一(Java多线程的基础).

    一.进程和线程的概念 进程:一次程序的执行称为一个进程,每个 进程有独立的代码和数据空间,进程间切换的开销比较大,一个进程包含1—n个线程.进程是资源分享的最小单位. 线程:同一类线程共享代码和数据空 ...

  6. MongoDB三节点高可用模式安装

    设备: 三个1G.20G.1核的虚拟机,系统是SentOS7 min 清除原始自数据目录: rm -fr /home/mongosingle/ 创建目录: mkdir -p /home/mongosi ...

  7. 总结各种排序算法【Java实现】

    一.插入类排序 1.直接插入排序 思想:将第i个插入到前i-1个中的适当位置 时间复杂度:T(n) = O(n²). 空间复杂度:S(n) = O(1). 稳定性:稳定排序. 如果碰见一个和插入元素相 ...

  8. sql执行机制

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp38 sql执行机制 1.对于普通的sql语句只有where条件的执行机制 ...

  9. Day-8: 面对对象编程

    面对过程的程序设计方法意在将函数分成子函数,再依次调用这些函数来解决问题. 而面对对象的程序设计方法,来源于自然界,类是实例的抽象,实例是类的具体.自定义出来的对象是类,而所有的数据都可以看成是对象, ...

  10. Ubuntu下安装NVIDIA显卡驱动的教训

    今天在ubuntu16.04版本下安装了NVIDIA的显卡驱动,真的是一波十六折: 首先是在英伟达的官网上查找你自己电脑的显卡型号然后下载相应的驱动. 网址:http://www.nvidia.cn/ ...