关于Promise

  • Promise实例一旦被创建就会被执行
  • Promise过程分为两个分支:pending=>resolvedpending=>rejected
  • Promise状态改变后,依然会执行之后的代码:
const warnDemo = ctx => {
const promise = new Promise(resolve => {
resolve(ctx);
console.log("After resolved, but Run"); // 依然会执行这个语句
});
return promise;
}; warnDemo("ctx").then(ctx => console.log(`This is ${ctx}`));

then方法

Console键入以下内容:

let t = new Promise(()=>{});
t.__proto__

可以看到,then方法是定义在原型对象Promise.prototype上的。

then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

写法

function func(args) {
// 必须返回一个Promise实例
return new Promise((resolve,reject)=>{
if(...){
resolve(...) // 传入resolve函数的参数
} else {
let err = new Error(...)
reject(err) // reject参数必须是Error对象
}
})
} func(ARGS).then(()=>{
// resolve 函数
},()=>{
// reject 函数
})

连续调用then

因为then方法返回另一个Promise对象。当这个对象状态发生改变,就会分别调用resolvereject

写法如下:

func(ARGS).then(()=>{
...
}).then(
()=>{ ... },
() => { ... }
)

实例

function helloWorld(ready) {
return new Promise((resolve,reject)=>{
if (ready){
resolve("Right")
} else {
let error = new Error("arg is false")
reject(error) // 传入Error对象
}
})
} helloWorld(false).then((msg)=>{ // true:helloWorld的参数
// 参数msg:在上面的Promise对象中传入了
console.log(msg)
},(error)=>{
console.log(error.message)
})

catch方法

等同于 .then(null, rejection)。另外,then方法指定的回调函数运行中的错误,也会被catch捕获。

所以,之前的写法可以改为:

function func(args) {
// 必须返回一个Promise实例
const promise = new Promise((resolve,reject)=>{
if(...){
resolve(...)
} else {
let err = new Error(...)
reject(err)
}
})
return promise
} func(ARGS).then(()=>{
// resolve 函数
}).catch(()=>{
// reject 函数
}).then(()=>{
// 没有错误就会跳过上面的catch
})...

finally方法

指定不管 Promise 对象最后状态如何,都会执行的操作。可以理解为then方法的实例,即在resolvereject里面的公共操作函数

all方法

用于将多个 Promise 实例,包装成一个新的 Promise 实例。它接收一个具有Iterator接口的参数。其中,item如果不是Promise对象,会自动调用Promise.resolve方法

以下代码:

const p = Promise.all([p1, p2, p3]); // p是新包装好的一个Promise对象

对于Promise.all()包装的Promise对象,只有实例的状态都变成fulfilled

可以用来操作数据库:

const databasePromise = connectDatabase();

const booksPromise = databasePromise
.then(findAllBooks); const userPromise = databasePromise
.then(getCurrentUser); Promise.all([
booksPromise,
userPromise
])
.then(([books, user]) => pickTopRecommentations(books, user));

或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。而对于每个promise对象,一旦它被自己定义catch方法捕获异常,那么状态就会更新为resolved而不是rejected

'use strict'
const p1 = new Promise((resolve, reject) => {
resolve('hello');
}).then(
result => result
).catch(
e => e
); const p2 = new Promise((resolve, reject) => {
throw new Error("p2 error")
}).then(
result => result
).catch(
// 如果注释掉 catch,进入情况2
// 否则,情况1
e => e.message
); Promise.all([p1, p2]).then(
result => console.log(result) // 情况1
).catch(
e => console.log("error in all") // 情况2
);

race方法

all方法类似,Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。而且只要有一个状态被改变,那么新的Promise状态会立即改变

也是来自阮一峰大大的例子,如果5秒内无法fetech,那么p状态就会变为rejected

const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p.then(response => console.log(response));
p.catch(error => console.log(error));

重要性质

状态只改变一次

Promise 的状态一旦改变,就永久保持该状态,不会再变了。

下面代码中,Promise对象resolved后,状态就无法再变成rejected了。

'use strict'

const promise = new Promise((resolve,reject)=>{
resolve('ok') // 状态变成 resolved
throw new Error("test") // Promise 的状态一旦改变,就永久保持该状态
})
promise.then((val)=>{
console.log(val)
}).catch((error)=>{
console.log(error.message) // 所以,无法捕获错误
})

错误冒泡

Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获

"吃掉错误"机制

Promise会吃掉内部的错误,并不影响外部代码的运行。所以需要catch,以防丢掉错误信息。

阮一峰大大给出的demo:

'use strict'

const someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// 下面一行会报错,因为x没有声明
resolve(x + 2);
});
}; someAsyncThing().then(function() {
console.log('everything is great');
}); setTimeout(() => { console.log(123) }, 2000);

还有如下demo

someAsyncThing().then(function() {
return someOtherAsyncThing();
}).catch(function(error) {
console.log('oh no', error);
// 下面一行会报错,因为y没有声明
y + 2;
}).catch(function(error) {
console.log('carry on', error);
});
// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError: y is not defined]

参考

  • demo基本可以在阮一峰的Es6讲解中找到,只是为了理解做了一些修改。
  • 还有网上的一些博客,这里就不一一说明了

欢迎技术交流,引用请注明出处。

个人网站:godbmw.com

Github:godbmw

es6中的Promise学习的更多相关文章

  1. ES6中Map数据结构学习笔记

    很多东西就是要细细的品读然后做点读书笔记,心理才会踏实- Javascript对象本质上就是键值对的集合(Hash结构),但是键只能是字符串,这有一定的限制. 1234 var d = {}var e ...

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

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

  3. es6中的promise对象

    Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...

  4. ES6中的Promise用法

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

  5. ES6中的Promise使用方法与总结

    在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的. 但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回 ...

  6. [转]JS - Promise使用详解2(ES6中的Promise)

    原文地址:https://www.hangge.com/blog/cache/detail_1638.html 2015年6月, ES2015(即 ECMAScript 6.ES6) 正式发布.其中  ...

  7. ES6中map数据结构学习

    在项目中遇到一个很恶心的需求,然后发现ES6中的map可以解决,所以简单学习了一下map. Javascript的Object本身就是键值对的数据结构,但实际上属性和值构成的是“字符串-值”对,属性只 ...

  8. ES6中的Promise和Generator详解

    目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...

  9. 深入解析ES6中的promise

    作者 | Jeskson来源 | 达达前端小酒馆 什么是Promise Promise对象是用于表示一个异步操作的最终状态(完成或失败)以及其返回的值. 什么是同步,异步 同步任务会阻塞程序的执行,如 ...

随机推荐

  1. 11-22 ArrayList

    自己定义一个类 public class Student{ public String name; //属性 public void fangfa(){ //方法 } } 在另一个java文件里可以调 ...

  2. 微信公众号UX分析—— 学生作业小结

    1. 不足: 1. 权威性:个人帐号,显得不够正式. 2. 排版问题: + 没有必要的外接端口,界面设计极度缺少排版.哪怕是个人公众号都不至于如此,更何况这是一个学校的教务平台. 3. 反应不及时或无 ...

  3. SQL Server使用证书最小粒度授权

    最近在项目中某个功能遇到了阻塞造成的Time out错误.所以需要在执行该功能的时候开启一个线程检测SQL Server中阻塞会话.但是程序本身使用的sql帐号本身不具备VIEW Sever Stat ...

  4. Swift5 语言指南(四) 基础知识

    Swift是iOS,macOS,watchOS和tvOS应用程序开发的新编程语言.尽管如此,Swift的许多部分对您在C和Objective-C中的开发经验都很熟悉. 雨燕提供了自己的所有基本C和Ob ...

  5. 使用cygwin中的awk工具进行mysql binlog日志查看[利刃篇]

    linux工具确实强悍,然而作为没有linux机器使用权以及开发没有使用linux进行的人,有时想用一些命令确实不方便,所以,才去试着用用cygwin,一款在windows平台上运行的类UNIX模拟环 ...

  6. Testing - 软件测试知识梳理 - 测试分类

    参考信息 软件测试分类 经典软件测试技术分类 软件测试方法汇总 简洁分类 对软件内部结构的深入程度 黑盒测试:又叫功能测试.数据驱动测试或基于需求规格说明书的功能测试. 该测试类别注重于测试软件的功能 ...

  7. Centos6.5安装Python2.7.9

    1. 问题背景 Centos6.5默认自带的python环境是2.6.6,python的一些特性没法使用,所以要对python进行升级,借鉴了网上其他同学的安装教程,但是还是遇到一些坑,不是那木顺利, ...

  8. http协议返回码

    有五种可能取值:1xx:指示信息--表示请求已接收,继续处理2xx:成功--表示请求已被成功接收.理解.接受3xx:重定向--要完成请求必须进行更进一步的操作4xx:客户端错误--请求有语法错误或请求 ...

  9. Ubuntu 16.04安装sogou 拼音输入法

    一.更换为国内的软件源 安装搜狗输入法之前请先更换为国内的软件源,否则无法解决依赖问题.首先,用以下命令打开源列表: sudo gedit /etc/apt/sources.list #用文本编辑器打 ...

  10. .net 连接kafka

    新建两个控制台项目,一个生产者,一个消费者,使用Nuget安装Confluent.Kafka 生产者 static void Main(string[] args) { var config = ne ...