1.Promise介绍

Promise最早是社区提出和实现,后面ES6将其写入标准,并原生提供Promise对象,是一种异步编程的解决方案,具体的概念大家可以去查看相关的资料。传统上处理异步都是以callback回调函数的方式完成,但是当回调嵌套的太多,便会使程序很难理解,如下所示

function a(cb){
console.log('a...');
cb('a');
}
function b(cb){
console.log('b...');
cb('b');
}
function c(cb){
console.log('c...');
cb('c');
}
a(() => b( () => c( () => {}) ));
a...
b...
c...

如果后面还有基于C函数的输出结果的逻辑,回调将是很大的困恼。

而使用Promise来处理这种异步回调将会非常的直观,Promise以同步的操作完成异步的处理,如下所示

function a(){
console.log('a...');
return 'a output';
}
function b(res){
console.log('b...');
console.log('get A:'+res);
return "b output";
}
function c(res){
console.log('c...');
console.log('get B:'+res);
}
new Promise((resolve,reject) => {setTimeout(resolve,1000)}).then(a).then(b).then(c);
Promise { <state>: "pending" }
a...
b...
get A:a output
c...
get B:b output

2.Promise的用法

Promise是一个构造函数,接收一个函数参数,该函数接收两个函数作为参数,分别是resolve,reject。这两个函数由Promise自己提供,无需自己部署。resolve函数将Promise的状态从'Pending'转为'Resolved',reject函数将状态从'Pending'转为'rejected'。

基本语法,如下所示

new Promise((resolve,reject) => {
if(success){ //异步处理成功
resolve();
}else{
reject();
}
}).then(onFulfilled,onRejected);

创建一个Promise实例,如下所示

var promise = new Promise((resolve,reject) => {console.log('hehe');resolve('resolved')});
promise.then((val) => console.log(val))
console.log('current');
hehe
current
resolved

resolve函数与reject函数调用时可以传递参数,一般给reject函数传递Error的实例,用于指出抛出的错误,传给reject函数的参数可以是一般的数值,也可以是Promise的实例,这时该Promise的实例状态由参数Promise实例的状态决定,如下所示

var p1 = new Promise((resolve,reject) => {
setTimeout(()=>{console.log('1秒后的 p1');resolve(p2);},1000);
});
var p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{console.log('2秒后的 p2');resolve('p2');},2000);
}); p1.then((val)=>console.log(val));
Promise { <state>: "pending" }
1秒后的 p1
2秒后的 p2
p2

如上所示,Promise是创建就立即执行,且then方法的回调函数将在当前脚本所有同步语句执行完执行,但是比定时器的队列优先级要高,如下所示

setTimeout(()=>console.log('settimeouting...'),0);
var promise = new Promise((resolve,reject) => {
console.log('promise constructing...');
reject(new Error('error'));
});
promise.then(null,(reason)=>console.log(reason));
promise constructing...
Promise { <state>: "pending" }
Error: error
堆栈跟踪:
promise<@debugger eval code:4:9
@debugger eval code:2:15 settimeouting...

Promise的原型方法then,该方法为promise实例添加状态改变时的回调函数,第一个参数是状态为resolved时的回调,第二个参数是状态为rejected的回调。如下所示

var p3 = new Promise((resolve,reject) => {
console.log('p3');
resolve('p3');
});
var p4 = new Promise((resolve,reject) => {
console.log('p4');
setTimeout(()=>resolve('p4'),1500);
});
p3.then(()=>p4).then((result) => console.log(result));//这里需要注意一点,如果then方法返回一个Promise实例,则下一个then回调需要等待该Promise实例的状态改变才会执行。
p3
p4
Promise { <state>: "pending" }
p4

Promise内部抛出的错误不会被捕获(Chrome浏览器除外),除非使用catch方法,如果在resolve之前抛出,则resolve不会执行,相反则相当于没有抛出错误,如下所示

var promise = new Promise((resolve,reject) => {
console.log('promise constructing...');
throw new Error('error');
resolve('haha');
});
promise.then((val)=>console.log(val));
promise constructing...
-------------------------------------------------------------
var promise = new Promise((resolve,reject) => {
console.log('promise constructing...');
resolve('haha');
throw new Error('error'); });
promise.then((val)=>console.log(val));
promise constructing...
haha

使用Promise的原型方法catch捕获错误,该方法其实是.then(null,reject)的别名,如下所示

var promise = new Promise((resolve,reject) => {
console.log('promise constructing...');
throw new Error('error');
resolve('haha');
});
promise.then((val)=>console.log(val)).catch((error)=>console.log(error)); promise constructing...
Promise { <state>: "pending" }
Error: error
堆栈跟踪:
promise<@debugger eval code:3:8
@debugger eval code:1:19

Promise的错误捕获可以使用then方法的第二个参数指定reject的回调函数,也可以使用Promise.prototype.catch方法捕获,但是一般推荐使用方法二,因为catch不仅能捕获到promise内部抛出的错误,then方法中的错误也能被捕获。但是在调用resolve方法之后,再抛出错误,不会被捕获,相当于没有抛出错误,如下所示

var promise = new Promise((resolve,reject) => {
throw new Error('promise error');
});
promise.then(null,(err)=>console.log(err));
Promise { <state>: "pending" }
Error: promise error
堆栈跟踪:
promise<@debugger eval code:2:9
@debugger eval code:1:19
---------------------------catch method-------------------
var promise = new Promise((resolve,reject) => {
reject(new Error('promise error'));
});
promise.catch((error)=>console.log(error));
Promise { <state>: "pending" }
Error: promise error
堆栈跟踪:
promise<@debugger eval code:2:9
@debugger eval code:1:19
---------------------------then方法中报错-------------------
var p5 = new Promise((resolve,reject) => {
resolve('hehe');
});
p5.then((val)=>val+x).catch((err)=>console.log(err));
Promise { <state>: "pending" }
ReferenceError: x is not defined
堆栈跟踪:
@debugger eval code:4:16

catch方法也是返回一个Promise,因此在catch后面还可以接着使用链式方法then,但这时then方法报错将不会被前面的catch捕获,如下所示

var p5 = new Promise((resolve,reject) => {
resolve('hehe');
});
p5.then((val)=>val+x).catch((err)=>console.log(err)).then((val)=>y+3);
Promise { <state>: "pending" }
ReferenceError: x is not defined
堆栈跟踪:
@debugger eval code:4:16

3.Promise.all

Promise.all方法可以将多个Promise实例[p1,p2,p3...]包装成一个Promise对象A,A的状态由p1,p2,p3...决定:如果p1,p2,p3...的状态都变为onfulfilled,A的状态才变为onfulfilled,且p1,p2,p3...的异步操作结果组成一个数组传给回调函数;但凡p1,p2,p3...中有一个状态变为了rejected,A的状态立即变为rejected,且第一个rejected的返回值会传给回调函数,如下所示

var p1 = new Promise((resolve,reject) => {
console.log('p1...');
setTimeout(()=>resolve('p1 resolved...'),1000);
});
var p2 = new Promise((resolve,reject) => {
console.log('p2...');
setTimeout(()=>resolve('p2 resolved...'),2000);
});
var p3 = new Promise((resolve,reject) => {
console.log('p3...');
setTimeout(()=>resolve('p3 resolved...'),3000);
}); Promise.all([p1,p2,p3]).then((args)=>{console.log('3S后的输出:');for(let v of args){console.log(v);}});
p1...
p2...
p3...
3S后的输出:
p1 resolved...
p2 resolved...
p3 resolved...
------------------------ 有一个Promise实例变为rejected ---------------
var p1 = new Promise((resolve,reject) => {
console.log('p1...');
setTimeout(()=>resolve('p1 resolved...'),1000);
});
var p2 = new Promise((resolve,reject) => {
console.log('p2...');
setTimeout(()=>resolve('p2 resolved...'),2000);
});
var p3 = new Promise((resolve,reject) => {
console.log('p3...');
setTimeout(()=>resolve('p3 resolved...'),3000);
});
var p4 = new Promise((resolve,reject) => {
console.log('p4...');
reject("p4 rejected...");
});
Promise.all([p1,p2,p3,p4]).then((args)=>console.log(args),(reason) => console.log(reason));
p1...
p2...
p3...
p4...
Promise { <state>: "pending" }
p4 rejected...

4.Promise.race

同Promise.all一样,该方法也是将多个Promise实例[p1,p2,p3...]包装成一个新的Promise实例B。"race"的字面意思就是竞争,所以[p1,p2,p3...]谁的状态先改变,B的状态立即改变一样的状态且第一个改变状态的promise实例的返回值传递给回调函数,如下所示

var p1 = new Promise((resolve,reject) => {
console.log('p1...');
setTimeout(()=>resolve('p1 resolved...'),1000);
});
var p2 = new Promise((resolve,reject) => {
console.log('p2...');
setTimeout(()=>resolve('p2 resolved...'),2000);
});
var p3 = new Promise((resolve,reject) => {
console.log('p3...');
setTimeout(()=>resolve('p3 resolved...'),3000);
}); Promise.race([p1,p2,p3]).then((val)=>console.log(val),(reason)=>console.log(reason)); p1...
p2...
p3...
Promise { <state>: "pending" }
p1 resolved...

5.Promise.resolve与Promise.reject

Promise.resolve是将给定的参数转换成一个Promise对象,如下所示

Promise.resolve(arg);//等同于new Promise((resolve)=>resolve(arg))
omise.resolve('resolve convert...').then((val)=>console.log(val));
Promise { <state>: "pending" }
resolve convert...

根据给定的参数类型不同,Promise.resolve有不同的动作:

A、参数为Promise实例,则直接返回该实例

B、参数为空,执行返回一个resolved状态的新Promise实例

C、参数为普通的数值或对象,则直接返回一个resolved状态的新Promise实例,如下所示

Promise.resolve({x:1}).then((val)=>console.log(val));
Promise { <state>: "pending" }
Object { x: 1 }

D、参数为thenable对象,既对象实现了then方法,此时返回一个新Promise实例并立即执行对象then方法,如下所示

var thenableObj = {
then(resolve,reject){
reject('test...');
}
};
Promise.resolve(thenableObj).then(null,(reason)=>console.log(reason)); Promise { <state>: "pending" }
test...

Promise.reject与Promise.resolve的用法一致,只是返回的Promise实例的状态为rejected,如下所示

Promise.reject('reject convert...').then(null,(reason) => console.log(reason));
Promise { <state>: "pending" }
reject convert...

6.给原生Promise对象扩展方法,如下所示

//一下两个函数来自raunyifeng博客
Promise.prototype.done = function (onFulfilled, onRejected) {
this.then(onFulfilled, onRejected)
.catch(function (reason) {
setTimeout(() => { throw reason }, 0);
});
};
该方法只要执行就可以捕获前面调用链中的错误
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
该方法不管Promise的实例的状态是否改变都会执行回调函数

ES6 - Note5:Promise的更多相关文章

  1. es6从零学习(二):promise

    es6从零学习(二):promise 一:promise的由来 某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱.由此,Promise的概念就由社区 ...

  2. ES6入门八:Promise异步编程与模拟实现源码

    Promise的基本使用入门: ——实例化promise对象与注册回调 ——宏任务与微任务的执行顺序 ——then方法的链式调用与抛出错误(throw new Error) ——链式调用的返回值与传值 ...

  3. es6学习3:promise

    promise含义: 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果. 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息.Pro ...

  4. ES6学习笔记五:Promise异步任务

    一:Promise对象 Promise对象代表一个异步操作,有三种状态:Pending(进行中).Resolved(已完成,又称 Fulfilled)和Rejected(已失败). 二:创建与使用 v ...

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

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

  6. ES6中的Promise用法

    Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...

  7. 深入浅出:promise的各种用法

    https://mp.weixin.qq.com/s?__biz=MzAwNTAzMjcxNg==&mid=2651425195&idx=1&sn=eed6bea35323c7 ...

  8. 深入理解ES6里的promise

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

  9. ES6特性:(阮一峰老师)学习总结

    ES6(阮一峰)学习总结   1.块级作用域的引入 在ES6之前,js只有全局作用域和函数作用域,ES6中let关键字为其引入了块级作用域. { var a = 5; let b = 6; } con ...

随机推荐

  1. 下载apk文件浏览器会直接打开并显示乱码的问题

    今天同事反映他的apk文件在自己的老项目中下载有问题:下载apk文件浏览器会直接打开并显示乱码,在别的项目中就没有问题. 后分析response的content-type发现,老项目的类型是text/ ...

  2. 构建 Android 应用程序一定要绕过的 30 个坑

    原文地址:Building Android Apps - 30 things that experience made me learn the hard way 原文作者:César Ferreir ...

  3. java入门第三步之数据库连接

    数据库连接可以说是学习web最基础的部分,也是非常重要的一部分,今天我们就来介绍下数据库的连接为下面学习真正的web打下基础 java中连接数据库一般有两种方式: 1.ODBC——Open Datab ...

  4. 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  5. SQL Server恢复软件SysTools SQL Recovery/SysTools SQL Server Recovery Manager

    SQL Server恢复软件SysTools SQL Recovery/SysTools SQL Server Recovery Manager http://www.systoolsgroup.co ...

  6. Linux 部署ASP.NET SQLite 应用 的坎坷之旅 附demo及源码

    Linux 部署ASP.NET SQLite 应用 的坎坷之旅.文章底部 附示例代码. 有一台闲置的Linux VPS,尝试着部署一下.NET 程序,结果就踏上了坑之路,不过最后算是完美解决问题,遂记 ...

  7. 动态Web API层

    返回总目录 本篇目录 构建动态Web API控制器 ForAll 方法 重写ForAll 方法 Http动词 动态Javascript代理 Ajax参数 单一服务脚本 Angular支持 Durand ...

  8. 领域驱动设计系列 (六):CQRS

    CQRS是Command Query Responsibility Seperation(命令查询职责分离)的缩写. 世上很多事情都比较复杂,但是我们只要进行一些简单的分类后,那么事情就简单了很多,比 ...

  9. CI-持续集成(2)-软件工业“流水线”技术实现

    1   概述 持续集成(Continuous Integration)是一种软件开发实践.在本系列文章的前一章节已经对其背景及理论体系进行了介绍.本小节则承接前面提出的理论构想进行具体的技术实现. & ...

  10. python实现grep

    import sys import os import re def usage(): print "[Usage]: python grep.py filename grepString. ...