深入理解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 相关文章推荐
Prototype源码浅析 String部分(二)
Jan 16 Javascript
JQuery实现倒计时按钮的实现代码
Mar 23 Javascript
JS 对输入框进行限制(常用的都有)
Jul 30 Javascript
使用js的replace()方法查找字符示例代码
Oct 28 Javascript
javascript显式类型转换实例分析
Apr 25 Javascript
javascript中加var和不加var的区别 你真的懂吗
Jan 06 Javascript
jQuery实现横向带缓冲的水平运动效果(附demo源码下载)
Jan 29 Javascript
JavaScript代码性能优化总结篇
May 15 Javascript
jQuery Dialog 取消右上角删除按钮事件
Sep 07 Javascript
详解vue.js 开发环境搭建最简单攻略
Jun 12 Javascript
React-Native左右联动List的示例代码
Sep 21 Javascript
three.js实现圆柱体
Dec 30 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
phpstrom使用xdebug配置方法
2013/12/17 PHP
在Yii框架中使用PHP模板引擎Twig的例子
2014/06/13 PHP
PHP实现在数据库百万条数据中随机获取20条记录的方法
2017/04/19 PHP
Jquery 获取表单text,areatext,radio,checkbox,select值的代码
2009/11/12 Javascript
jQuery 翻牌或百叶窗效果(内容三秒自动切换)
2012/06/14 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
2013/10/23 Javascript
Jquery 模拟用户点击超链接或者按钮的方法
2013/10/25 Javascript
js字母大小写转换实现方法总结
2013/11/13 Javascript
AngularJS学习笔记之TodoMVC的分析
2015/02/22 Javascript
javascript+html5实现绘制圆环的方法
2015/07/28 Javascript
jQuery超精致图片轮播幻灯片特效代码分享
2015/09/10 Javascript
jquery移动端TAB触屏切换实现效果
2020/12/22 Javascript
在Html中使用Requirejs进行模块化开发实例详解
2016/04/15 Javascript
javascript获取select标签选中的值
2016/06/04 Javascript
jQuery时间验证和转换为标准格式的时间格式
2017/03/06 Javascript
vue2.x select2 指令封装详解
2017/10/12 Javascript
浅谈Vue SPA 首屏加载优化实践
2017/12/15 Javascript
vue 实现边输入边搜索功能的实例讲解
2018/09/16 Javascript
JavaScript遍历数组的方法代码实例
2020/01/14 Javascript
vue实现图片上传功能
2020/05/28 Javascript
javascript+Canvas实现画板功能
2020/06/23 Javascript
[04:49]期待西雅图之战 2016国际邀请赛中国区预选赛WINGS战队赛后采访
2016/06/29 DOTA
Python迭代器与生成器基本用法分析
2018/07/26 Python
Python3 实现文件批量重命名示例代码
2019/06/03 Python
在Django model中设置多个字段联合唯一约束的实例
2019/07/17 Python
css3中用animation的steps属性制作帧动画
2019/04/25 HTML / CSS
CSS3 2D模拟实现摩天轮旋转效果
2016/11/16 HTML / CSS
生物技术专业研究生自荐信
2013/09/22 职场文书
幼儿园中班下学期评语
2014/04/18 职场文书
北京奥运会主题口号
2014/06/13 职场文书
自我管理的活动方案
2014/08/25 职场文书
学校计划生育责任书
2015/05/09 职场文书
热血教师观后感
2015/06/10 职场文书
2016年过年放假安排通知
2015/08/18 职场文书
一波干货,会议主持词开场白范文
2019/05/06 职场文书
SQLServer中JSON文档型数据的查询问题解决
2021/06/27 SQL Server