深入理解JS异步编程-Promise


Posted in Javascript onJune 03, 2019

前言

“JS 是基于单线程事件循环”的概念构建的,回调函数不会立即执行,由事件轮询去检测事件是否执行完毕,当执行完有结果后,将结果放入回调函数的参数中,然后将回调函数添加到事件队列中等待被执行。

同时也讲了回调函数的问题:

一是“回调地狱”,因为异步回调函数的特点:回调函数是作为异步函数的参数,一层一层嵌套,当嵌套过多,将使代码逻辑变得混乱,也无法做好错误捕捉和处理(只能在回调函数内部 try catch)。

二是回调的执行方式不符合自然语言的线性思维方式,不容易被理解。

三是控制反转(控制权在其他人的代码上),假如异步函数是别人提供的库,我们把回调函数传进去,我们并不能知道异步函数在调用回调函数之外做了什么事情。

func1(() => {
func2(() => {
func3(() => {
func4(() => {
try {
...
} catch (err){
...
}
})
});
});
});

一、Promise 原理

首先,Promise 中文翻译为“承诺”, 是 JavaScript 的一种对象,表示承诺终将返回一个结果,无论成功还是失败。
Promise 有三个状态:等待中(pending),完成(fullfilled),失败(rejected), Promise 的设计具有原子性,状态一旦从 pending 状态转换为 fullfilled 状态或者 rejected 状态后,将不能被改变。

深入理解JS异步编程-Promise

var promise1 = new Promise((resolve, reject) => {
console.log("Promise 构造器会立即执行");
setTimeout(function (){
if(true) {
resolve("完成");
} else {
reject("失败");
}
}, 1000);
})
promise1
.then((result) => {
// do something
console.log(result);
return 1
// return Promise.resolve(1); // 返回一个决议为成功的 promise 实例
// return Promise.reject("error"); // 返回一个决议为拒绝的 Promise 实例
})
.then((result) => {
// .then() 方法会返回一个 promise, 完成调用的参数为前一个 promise 的返回值或者决议值。
// do other things
console.log(result);
throw new Error("错误") // 抛出错误是隐式拒绝
})
.catch((error) => {
// 捕捉错误
console.log(error)
})
.then(() => {
// 还能继续执行!
})
.finally(() => {
// always do somethings
console.log("finally!")
})

二、Promise 的优势

1.链式调用

Promise 使用 then 方法后还会返回一个新的 Promise 对象,便于我们传递状态数据,同时链式写法接近于同步写法,更符合线性思维。

2.错误捕捉

相比回调函数的错误无法在外部捕捉的问题,Promise 能够为一连串的异步调用提供错误处理。

3.控制反转再反转

由于第三方提供的异步函数,无法保证回调函数如何被执行,但是 Promise 的特点,能够保证异步函数只能被 resolve 一次,以及始终以异步的形式执行代码。

4.可以利用 Promise.all 和 Promise.race 来解决 Promise 始终未决议和并行 Promise 嵌套的问题

三、Promise 的不足

1.每个 .then() 都是一个独立的作用域

加入有很多个 .then() 方法,就会创建很多个独立的作用域,那么将只能通过外面包裹一层函数作用域的闭包来共享状态数据

2.无法取消单个 .then()

当 Promise 链中任意一个 .then() 方法中有语句执行错误后,尽管经过 catch 方法的错误处理,还是并不会中断整个 Promise 链的执行。

3.无法得知进度

由于 Promise 只能从 pending 到 fullfilled 或 rejected 状态,无法得知 pending 阶段的进度。

四、Promise 应用

// Promise 封装 ajax
function fetch(method, url, data){
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
var method = method || "GET";
var data = data || null;
xhr.open(method, url, true);
xhr.onreadystatechange = function() {
if(xhr.status === 200 && xhr.readyState === 4){
resolve(xhr.responseText);
} else {
reject(xhr.responseText);
}
}
xhr.send(data);
})
}
// 使用
fetch("GET", "/some/url.json", null)
.then(result => {
console.log(result);
})
// 封装 nodejs error first 风格回调
function readFile(url) {
return new Promise((resolve, reject) => {
fs.readFile(url,'utf8', (err, data) => {
if(err) {
reject(err);
return;
}
resolve(data)
}) 
})
}

五、总结

Promise 是 ES6 提出的简化异步流程控制新规范,强调异步任务的完成状态且具有原子性,这使得我们的代码更容易追踪和维护。Promise 在事件轮询中属于异步事件队列中的微任务,而微任务总是一次性全部执行,而宏任务是每轮轮询执行一个。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
两种WEB下的模态对话框 (asp.net或js的分别实现)
Dec 02 Javascript
jquery解析xml字符串示例分享
Mar 25 Javascript
jQuery插件passwordStrength密码强度指标详解
Jun 24 Javascript
js添加千分位的实现代码(超简单)
Aug 01 Javascript
jQuery实现按比例缩放图片的方法
Apr 29 jQuery
详解vue-cli中配置sass
Jun 21 Javascript
利用nvm管理多个版本的node.js与npm详解
Nov 02 Javascript
详解如何在微信小程序开发中正确的使用vant ui组件
Sep 13 Javascript
详解Node.js一行命令上传本地文件到服务器
Apr 22 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
Nov 01 Javascript
Vue前端项目部署IIS的实现
Jan 06 Javascript
Vue向后台传数组数据,springboot接收vue传的数组数据实例
Nov 12 Javascript
模块化react-router配置方法详解
Jun 03 #Javascript
react 组件传值的三种方法
Jun 03 #Javascript
angular使用md5,CryptoJS des加密的方法
Jun 03 #Javascript
Node.js 的 GC 机制详解
Jun 03 #Javascript
微信小程序蓝牙连接小票打印机实例代码详解
Jun 03 #Javascript
react-native滑动吸顶效果的实现过程
Jun 03 #Javascript
vue-cli 3 全局过滤器的实例代码详解
Jun 03 #Javascript
You might like
mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
2007/03/15 PHP
PHP cookie,session的使用与用户自动登录功能实现方法分析
2019/06/05 PHP
Laravel框架集合用法实例浅析
2020/05/14 PHP
PHP加MySQL消息队列深入理解
2021/02/27 PHP
用C/C++来实现 Node.js 的模块(二)
2014/09/24 Javascript
jquery幻灯片插件bxslider样式改进实例
2014/10/15 Javascript
js中最容易被忽视的事件问题大总结
2016/05/15 Javascript
js中常用的Tab切换效果(推荐)
2016/08/30 Javascript
实例解析js中try、catch、finally的执行规则
2017/02/24 Javascript
AngularJS折叠菜单实现方法示例
2017/05/18 Javascript
JS基于设计模式中的单例模式(Singleton)实现封装对数据增删改查功能
2018/02/06 Javascript
linux 下以二进制的方式安装 nodejs
2020/02/12 NodeJs
python使用点操作符访问字典(dict)数据的方法
2015/03/16 Python
python获取文件路径、文件名、后缀名的实例
2018/04/23 Python
删除python pandas.DataFrame 的多重index实例
2018/06/08 Python
Python爬取qq空间说说的实例代码
2018/08/17 Python
python生成以及打开json、csv和txt文件的实例
2018/11/16 Python
python中使用 xlwt 操作excel的常见方法与问题
2019/01/13 Python
浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)
2019/08/12 Python
Python 利用高德地图api实现经纬度与地址的批量转换
2019/08/14 Python
PyTorch中topk函数的用法详解
2020/01/02 Python
python解释器pycharm安装及环境变量配置教程图文详解
2020/02/26 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
python爬虫scrapy框架的梨视频案例解析
2021/02/20 Python
英国拖鞋购买网站:Bedroom Athletics
2020/02/28 全球购物
毕业生自荐书
2013/12/18 职场文书
市场营销专业毕业生求职信
2014/03/26 职场文书
软环境建设心得体会
2014/09/09 职场文书
四风问题个人自查剖析材料思想汇报
2014/09/21 职场文书
道路交通事故人身损害赔偿协议书
2014/11/19 职场文书
战马观后感
2015/06/08 职场文书
2015年乡镇组织委员工作总结
2015/10/23 职场文书
抖音短视频(douyin)去水印工具的实现代码
2021/03/30 Javascript
CocosCreator入门教程之网络通信
2021/04/16 Javascript
css3新特性的应用示例分析
2022/03/16 HTML / CSS
《吸血鬼:避世 血猎》官宣4.27发售 系列首款大逃杀
2022/04/03 其他游戏