es6中的Promise学习
关于Promise
Promise
实例一旦被创建就会被执行Promise
过程分为两个分支:pending=>resolved
和pending=>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
对象。当这个对象状态发生改变,就会分别调用resolve
和reject
写法如下:
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
方法的实例,即在resolve
和reject
里面的公共操作函数
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学习的更多相关文章
- ES6中Map数据结构学习笔记
很多东西就是要细细的品读然后做点读书笔记,心理才会踏实- Javascript对象本质上就是键值对的集合(Hash结构),但是键只能是字符串,这有一定的限制. 1234 var d = {}var e ...
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...
- es6中的promise对象
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...
- ES6中的Promise用法
Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...
- ES6中的Promise使用方法与总结
在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的. 但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回 ...
- [转]JS - Promise使用详解2(ES6中的Promise)
原文地址:https://www.hangge.com/blog/cache/detail_1638.html 2015年6月, ES2015(即 ECMAScript 6.ES6) 正式发布.其中 ...
- ES6中map数据结构学习
在项目中遇到一个很恶心的需求,然后发现ES6中的map可以解决,所以简单学习了一下map. Javascript的Object本身就是键值对的数据结构,但实际上属性和值构成的是“字符串-值”对,属性只 ...
- ES6中的Promise和Generator详解
目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...
- 深入解析ES6中的promise
作者 | Jeskson来源 | 达达前端小酒馆 什么是Promise Promise对象是用于表示一个异步操作的最终状态(完成或失败)以及其返回的值. 什么是同步,异步 同步任务会阻塞程序的执行,如 ...
随机推荐
- tar打包如何不打包某一个文件夹(排除某些文件夹)
tar打包如何不打包某一个文件夹(排除某些文件夹) 问题描述: 最近想备份一下Tomcat运行的的功能文件,以防特殊情况的发生.但是在实际操作的过程中发现,可能是由于Unix/Linux版本太老的原因 ...
- Codeforces Round #514 (Div. 2) B - Forgery
这个题我一开始没思路,最后也没思路 2个小时一直没思路 本来还想解释题意的,写了半天发现解释的不是很清楚,你还是google翻译一下吧 这个题解法是这样的: 首先,给你图案里面有很多的点,每个点的周围 ...
- String str.trim()
String.trim() 方法不仅仅是去除字符串两端的空格字符,它能去除25种字符: ('/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', ...
- CUDA-存储器
1.类型(8种) register: GPU片内 device可读\写 shared memory:GPU片内 device可读\写 local memory:板载显存 device可读\写 cons ...
- MySQL DDL--ghost执行模板和参数
常用GHOST模板 ##================================================## mysql_ip="127.0.0.1" mysql_ ...
- EF生成实体自动添加数据库字段注释
我们在用EF从数据库生成模型的时候,默认实体类是没有注释的,但是我们已经在数据库字段添加说明了,能不能自动把注释也拿过来? 答案是:能. 那么我们开始 首先随便开一个ASP.NET MVC项目,我 ...
- electron 使用 node-ffi 调用 C++ 动态链接库(DLL)
一.为什么需要使用DLL 需要使用系统 API 操作或扩展应用程序: 需要调用第三方的接口API,特别是与硬件设备进行通信,而这些接口 API 基本上都是通过 C++ 动态链接库(DLL)实现的: 需 ...
- linux下 /usr/bin/ld: 找不到 -ldhnetsdk的解决方法
linux下使用Qt编译程序的时候,安装了程序自带的链接库之后,仍然上报这个错误, 发现系统上报这个错误: /usr/bin/ld: 找不到 -ldhnetsdk 经过仔细的定位,终于解决了,这里把思 ...
- 使用autogen生成应用程序遇到问题及解决方法
从github上下载的代码,运行autogen.sh的时候,上报错误: $ ./autogen.sh --prefix=/usr./autogen.sh: 10: ./autogen.sh: auto ...
- Shell - 文本处理
珠玉在前,不再赘言. 常用命令 LinuxShell文本处理工具集锦 数据工程师常用的Shell命令 文件和目录管理 简明教程 AWK简明教程 SED简明教程 命令详解 linux sort,uniq ...