深入理解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 相关文章推荐
实例:用 JavaScript 来操作字符串(一些字符串函数)
Feb 15 Javascript
datePicker——日期选择控件(with jquery)
Feb 20 Javascript
基于jQuery的js分页代码
Jun 10 Javascript
javascript实现dom元素可拖动
Mar 21 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
Nov 23 Javascript
jQuery插件echarts实现的单折线图效果示例【附demo源码下载】
Mar 04 Javascript
Angular.js组件之input mask对input输入进行格式化详解
Jul 10 Javascript
linux 后台运行node服务指令方法
May 23 Javascript
vue-router重定向不刷新问题的解决
Jun 25 Javascript
对Vue2 自定义全局指令Vue.directive和指令的生命周期介绍
Aug 30 Javascript
layui 实现加载动画以及非真实加载进度的方法
Sep 23 Javascript
Vue项目中使用jsonp抓取跨域数据的方法
Nov 10 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
如何去掉文章里的 html 语法
2006/10/09 PHP
global.php
2006/12/09 PHP
手把手教你使用DedeCms的采集的图文教程
2007/03/11 PHP
php结合表单实现一些简单功能的例子
2011/06/04 PHP
php学习之 循环结构实现代码
2011/06/09 PHP
从零开始学YII2框架(四)扩展插件yii2-kartikgii
2014/08/20 PHP
PHP读取文件或采集时解决中文乱码
2021/03/09 PHP
Js 获取Gridview选中行的内容操作步骤
2013/02/05 Javascript
jquery实现鼠标拖拽滑动效果来选择数字的方法
2015/05/04 Javascript
jquery实现很酷的网页顶部图标下拉菜单效果
2015/08/22 Javascript
JS实现网页顶部向下滑出的全国城市切换导航效果
2015/08/22 Javascript
基于OL2实现百度地图ABCD marker的效果
2015/10/01 Javascript
JavaScript阻止回车提交表单的方法
2015/12/30 Javascript
javascript多物体运动实现方法分析
2016/01/08 Javascript
Boostrap模态窗口的学习小结
2016/03/28 Javascript
AngularJS压缩JS技巧分析
2016/11/08 Javascript
AngularJS 单选框及多选框的双向动态绑定
2017/04/20 Javascript
关于vue-router的beforeEach无限循环的问题解决
2017/09/09 Javascript
Vue.js实现开发购物车功能的方法详解
2019/02/22 Javascript
微信小程序实现同一页面取值的方法分析
2019/04/30 Javascript
微信小程序之滑动页面隐藏和显示组件功能的实现代码
2020/06/19 Javascript
Element DateTimePicker日期时间选择器的使用示例
2020/07/27 Javascript
[45:06]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第二场 11.28
2020/12/02 DOTA
[47:43]完美世界DOTA2联赛PWL S3 Magama vs GXR 第二场 12.19
2020/12/24 DOTA
python基础教程之序列详解
2014/08/29 Python
Python切片工具pillow用法示例
2018/03/30 Python
Python多线程原理与用法详解
2018/08/20 Python
Django基础知识 URL路由系统详解
2019/07/18 Python
python网络编程:socketserver的基本使用方法实例分析
2020/04/09 Python
Python实现Keras搭建神经网络训练分类模型教程
2020/06/12 Python
记一次Django响应超慢的解决过程
2020/09/17 Python
如何反序的迭代一个序列?how do I iterate over a sequence in reverse order
2012/02/04 面试题
学习党章思想汇报
2014/01/07 职场文书
岗位竞聘书范文
2014/03/31 职场文书
三八妇女节新闻稿
2015/07/17 职场文书
企业管理不到位检讨书
2019/06/27 职场文书