深入理解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 相关文章推荐
JS中showModalDialog 的使用解析
Apr 17 Javascript
基于JavaScript 数据类型之Boolean类型分析介绍
Apr 19 Javascript
JavaScript的jQuery库中ready方法的学习教程
Aug 14 Javascript
jquery validate demo 基础
Oct 29 Javascript
jquery获取所有选中的checkbox实现代码
May 26 Javascript
JS实现搜索框文字可删除功能
Dec 28 Javascript
js Canvas绘制圆形时钟教程
Feb 06 Javascript
本地存储localStorage用法详解
Jul 31 Javascript
jQuery 开发之EasyUI 添加数据的实例
Sep 26 jQuery
JS实现判断数组是否包含某个元素示例
May 24 Javascript
js图片无缝滚动插件使用详解
May 26 Javascript
vue父子组件间引用之$parent、$children
May 20 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
phpmyadmin打开很慢的解决方法
2014/04/21 PHP
php精确的统计在线人数的方法
2015/10/21 PHP
PHP实现微信支付(jsapi支付)流程步骤详解
2018/03/15 PHP
jQuery Jcrop插件实现图片选取功能
2011/11/23 Javascript
情人节专属 纯js脚本1k大小的3D玫瑰效果
2012/02/11 Javascript
javascript闭包的高级使用方法实例
2013/07/04 Javascript
jQuery 中$(this).index与$.each的使用指南
2014/11/20 Javascript
JavaScript中的对象序列化介绍
2014/12/30 Javascript
JS正则匹配中文的方法示例
2017/01/06 Javascript
vue Render中slots的使用的实例代码
2017/07/19 Javascript
一个Js文件函数中调用另一个Js文件函数的方法演示
2017/08/14 Javascript
vue2.0 + element UI 中 el-table 数据导出Excel的方法
2018/03/02 Javascript
小程序开发基础之view视图容器
2018/08/21 Javascript
angular.js实现列表orderby排序的方法
2018/10/02 Javascript
详解微信小程序支付流程与梳理
2019/07/16 Javascript
js实现单元格拖拽效果
2020/02/10 Javascript
webpack 动态批量加载文件的实现方法
2020/03/19 Javascript
朴素贝叶斯算法的python实现方法
2014/11/18 Python
matplotlib savefig 保存图片大小的实例
2018/05/24 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
django 通过URL访问上传的文件方法
2019/07/28 Python
PyCharm 2020.2.2 x64 下载并安装的详细教程
2020/10/15 Python
HTML5+CSS3网页加载进度条的实现,下载进度条的代码实例
2016/12/30 HTML / CSS
马来西亚网上购物:Youbeli
2018/03/30 全球购物
英国在线潜水商店:Simply Scuba
2019/03/25 全球购物
迪卡侬中国官网:Decathlon中国
2020/08/10 全球购物
护理专业大学生自我推荐信
2014/01/25 职场文书
八荣八耻的活动方案
2014/08/16 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
2016新年慰问信范文
2015/03/25 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
企业承诺书格式范文
2015/04/28 职场文书
大学生社会实践活动总结报告
2015/05/06 职场文书
2015暑假假期总结
2015/07/13 职场文书
保护环境建议书作文500字
2015/09/14 职场文书
Win11 Dev 预览版25174.1000发布 (附更新修复内容汇总)
2022/08/05 数码科技