异步编程promise
异步编程发展
异步编程经历了 callback、promise、async/await、generator四个阶段,其中promise和async/await使用最为频繁,而generator因为语法晦涩难懂,很少使用。
本文主要讲述promise如何使用。
promise语法
promise的三种状态
pending状态:
未调用resolve或者reject时候处于pending状态
fullfilled状态:
调用resolve后处于fullfilled状态
rejected状态:
调用reject后处于rejected状态。如果在pending状态时候,执行任务抛出错误,则变成reject状态。
promise对象的方法then、catch、all、race、allSettled
then
then方法不传参数
// 第一个promise
const p = new Promise(resolve => {
throw new Error('test'); // 抛出错误
});
// 第二个promise
p.then(
() => {} // 这里是状态变为fullfilled的回调函数
// 这里空着的,本应该填的是状态变为rejected的回调函数,所以不传递参数
)
// 第三个promise
.then(
data => console.log('resolve', data),
err => console.log('reject', err)
)
// 运行结果:reject Error: test
// 可见,第一个promise抛出的错误,即使第二个promise没有rejected回调函数,第三个promise的rejected回调函数依旧能接受到参数
// 结论:无论onFullfilled还是onRjected中,上一个promise不对参数进行处理,下一个promise进行处理
then方法回调不返回值
// 第一个promise
const p = new Promise(resolve => {
resolve('test')
});
// 第二个promise
p.then(() => {
() => {} // 状态变成fullfilled的回调函数,没有返回值
})
// 第三个promise
.then(
data => console.log('resolve', data),
err => console.log('reject', err)
)
// 运行结果:resolve undefined
// 第一个promise
const p = new Promise(() => {
throw new Error('error');
});
// 第二个promise
p.then(
() => {},
() => {} // 状态变成rejected的回调函数,没有返回值
)
// 第三个promise
.then(
data => console.log('resolve', data),
err => console.log('reject', err)
)
// 运行结果:resolve undefined
// 结论:无论onFullfilled还是onRjected中,then方法回调不返回值,状态都会变成fullfilled,走fullfilled的回调函数
then方法回调返回普通值
var p = new Promise(resolve => {
throw new Error('test');
});
p.then(
() => { return 'a' },
() => { return {b: 1} }
).then(
(data) => console.log("resolve", data),
(err) => console.log("reject", err)
);
// 运行结果:resolve {b: 1}
// 结论:无论onFullfilled还是onRjected中,then方法回调返回普通值,状态都会变成fullfilled,走fullfilled的回调函数
then方法回调返回promise
var p = new Promise(resolve => {
throw new Error('test');
});
p.then(
() => { return 'a' },
() => { return Promise.resolve('test') }
).then(
(data) => console.log("resolve", data),
(err) => console.log("reject", err)
);
// 运行结果:resolve test
// 结论:无论onFullfilled还是onRjected中,返回一个promise对象,则以该promise的任务和状态返回新的promise
then方法回调返回thenable对象
var p = new Promise((r) => {throw new Error('test')});
p.then(
() => ({then: function(resolvePromise, rejectPromise) {resolvePromise('resolvePromise')}}),
e => ({then: function(resolvePromise, rejectPromise) {rejectPromise('rejectPromise')}})
)
.then(
data => console.log('resolve', data),
e => console.log('reject', e)
);
// 运行结果:reject rejectPromise
// 结论:无论onFullfilled中还是onRejected中,返回一个thenable对象,则调用该对象的then方法,该then方法接收两个参数resolvePromise和rejectPromise。
// 如果then中调用了resolvePromise,则返回的promise状态置为fullfilled,如果then中调用了rejectPromise,或者then中抛出异常,则返回的Promise状态置为rejected。
// 在调用resolvePromise或者rejectPromise之前,返回的promise处于pending状态。
then方法回调抛出错误
无论onFullfilled中还是onRejected中,抛出错误,则以rejected为状态返回新promise。
catch
catch方法和then方法的reject回调用法相同,如果这时候任务处于rejected状态,则直接执行catch,catch的参数就是reject的reason;
var p = new Promise(resolve => {
throw new Error('test');
});
// catch写法
p.catch((err) => {
console.log(err);
})
// 两种写法等价
p.then(
undefined,
(err) => {
console.log(err);
}
)
all
Promise.all方法接收一个promise数组作为参数,返回一个promise,当参数的数组中的所有promise都resolve时候,返回的promise才会resolve;而若有一个参数的数组中的promise reject,返回的promise就会reject。
var p1 = Promise.resolve(1);
var p2 = new Promise(resolve => {
setTimeout(() => {
resolve(2);
}, 1000);
})
Promise.all([p1, p2])
.then(
([result1, result2]) => {console.log('resolve', result1, result2);}
)
// 运行结果:resolve 1 2
race
Promise.race接收一个promise数组作为参数,返回一个新的promise。当参数数组中其中一个promise resolve或者reject,返回的promise就相应地改变状态。
var p1 = Promise.reject(1);
var p2 = new Promise(resolve => {
setTimeout(() => {
resolve(2);
}, 1000);
});
Promise.race([p1, p2])
.then(
data => {console.log('resolve', data);},
e => {console.log('reject', e);}
);
// 运行结果:reject 1
allSettled
Promise.allSettled用于多个异步任务都结束(完成或者失败)时候,再执行后续任务的场景。
Promise.allSettled接收一个promise数组作为参数,返回一个promise。当参数数组中所有promise状态改变后,返回的promise变为fullfilled状态。
返回的promise的onFullfilled参数接收一个结果数组作为参数,数组对应Promise.allSettled传入的promise数组。结果数组每个元素是一个对象,格式固定:{status, value, reason},标识状态、resolve返回值、reject原因。
var p1 = Promise.reject(1);
var p2 = new Promise(resolve => {
setTimeout(() => {
resolve(2);
}, 1000);
});
Promise.allSettled([p1, p2])
.then(
data => {console.log('resolve', data);},
);
// 运行结果:resolve [{status: "rejected", reason: 1}, {status: "fulfilled", value: 2}]
异步编程promise的更多相关文章
- 简单实现异步编程promise模式
本篇文章主要介绍了异步编程promise模式的简单实现,并对每一步进行了分析,需要的朋友可以参考下 异步编程 javascript异步编程, web2.0时代比较热门的编程方式,我们平时码的时候也或多 ...
- 异步编程——promise
异步编程--promise 定义 Promise是异步编程的一个解决方案,相比传统的解决方法--回调函数,使用Promise更为合理和强大,避免了回调函数之间的层层嵌套,也使得代码结构更为清晰,便于维 ...
- 异步编程Promise/Deferred、多线程WebWorker
长期以来JS都是以单线程的模式运行的,而JS又通常应用在操作用户界面和网络请求这些任务上.操作用户界面时不能进行耗时较长的操作否则会导致界面卡死,而网络请求和动画等就是耗时较长的操作.所以在JS中经常 ...
- 简述异步编程&Promise&异步函数
前言:文章由本人在学习之余总结巩固思路,不足之前还请指出. 一.异步编程 首先我们先简单来回顾一下同步API和异步API的概念 1.同步API:只有当前的API执行完成之前,才会执行下一个API 例: ...
- AnjularJS异步编程 Promise和$q
Promise,是一种异步处理模式. js代码的函数嵌套会使得程序执行异步代码时很难调试.因为多重嵌套的函数无法确定何时触发回调. 如: funA(arg1,arg2,function(){ func ...
- es6异步编程 Promise 讲解 --------各个优点缺点总结
//引入模块 let fs=require('fs'); //异步读文件方法,但是同步执行 function read(url) { //new Promise 需要传入一个executor 执行器 ...
- 你所必须掌握的三种异步编程方法callbacks,listeners,promise
目录: 前言 Callbacks Listeners Promise 前言 coder都知道,javascript语言运行环境是单线程的,这意味着任何两行代码都不能同时运行.多任务同时进行时,实质上形 ...
- JavaScript异步编程 ( 一 )
1. 异步编程 Javascript语言的执行环境是"单线程"(single thread).所谓"单线程",就是指一次只能完成一件任务.如果有多个任务,就必须 ...
- JavaScript异步编程(1)- ECMAScript 6的Promise对象
JavaScript的Callback机制深入人心.而ECMAScript的世界同样充斥的各种异步操作(异步IO.setTimeout等).异步和Callback的搭载很容易就衍生"回调金字 ...
随机推荐
- React key究竟有什么作用?深入源码不背概念,五个问题刷新你对于key的认知
壹 ❀ 引 我在[react]什么是fiber?fiber解决了什么问题?从源码角度深入了解fiber运行机制与diff执行一文中介绍了react对于fiber处理的协调与提交两个阶段,而在介绍协调时 ...
- PTA(BasicLevel)-1016 部分A+B
一.问题定义 正整数 a的"Da(为 1 位整数)部分"定义为由a中所有Da组成的新整数Pa.例如:给定8,Da = 6,则a的"6 部分"Pa是66,因为a ...
- 2019 CSP-S 初赛解析
因为我不会设置用博客园显示Markdown语法,所以在洛谷也写了一份:传送门 一起讨论的这套卷.题干 然后还有一些可以借鉴一下的解析 选择: T1. 注意运算顺序: a%3=1 --> (int ...
- 分库分表真的适合你的系统吗?聊聊分库分表和NewSQL如何选择
曾几何时,"并发高就分库,数据大就分表"已经成了处理 MySQL 数据增长问题的圣经. 面试官喜欢问,博主喜欢写,候选人也喜欢背,似乎已经形成了一个闭环. 但你有没有思考过,分库分 ...
- 自定义nginx的日志格式存储到Filebeat和Logstash
vim /etc/nginx/nginx.conf log_format main '$remote_addr - $remote_user [$time_local] ' '"$reque ...
- jdbc 06: 实现登陆页面
jdbc连接mysql,实现简单的登陆验证 package com.examples.jdbc.o6_实现登录界面; import java.sql.*; import java.util.HashM ...
- go交叉编译,部署到linux上出现cannot execute binray file的解决方案
写在前面: 了解过常见的项目部署方式后,打算先从最简单的方式开始.没想到踩了大坑.先说下整个部署的过程. 博主是在window上生成linux上的可执行文件.. 具体过程: 1.首先按照网上说的 ...
- zabbix 6.2.0部署
zabbix 6.2官方部署文档 https://www.zabbix.com/documentation/6.2/en/manual/installation/install下载zabbix6.2安 ...
- 【洛谷P1754 球迷购票问题】题解
传送门 卡特兰数经典 \(\texttt{AB}\) 分拆问题. 分析: 题意相当于排列 \(n\) 个 \(\texttt A\) 和 \(n\) 个 \(\texttt B\),使得相邻 \(\t ...
- SpringBoot的创建和特性
一.SpringBoot的特点 创建独立的Spring应用程序 直接嵌入Tomcat.Jetty或Undertow(无需部署WAR文件) 提供自以为是的"starter"依赖项,以 ...