深入理解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 相关文章推荐
Jquery Validation插件防止重复提交表单的解决方法
Mar 05 Javascript
不使用中间变量,交换int型的 a, b两个变量的值。
Oct 29 Javascript
JavaScript获取网页支持表单字符集的方法
Apr 02 Javascript
深入学习jQuery Validate表单验证
Jan 18 Javascript
基于Javascript实现二级联动菜单效果
Mar 04 Javascript
浅谈String.valueOf()方法的使用
Jun 06 Javascript
在javascript中使用com组件的简单实现方法
Aug 17 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
Feb 20 Javascript
全面解析Node.js 8 重要功能和修复
Jun 02 Javascript
javascript获取指定区间范围随机数的方法
Sep 08 Javascript
详解JavaScript的变量
Apr 04 Javascript
JS实现碰撞检测效果
Mar 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
最令PHP初学者们头痛的十四个问题
2007/01/15 PHP
golang、python、php、c++、c、java、Nodejs性能对比
2017/03/12 NodeJs
Centos7安装swoole扩展操作示例
2020/03/26 PHP
JAVASCRIPT对象及属性
2007/02/13 Javascript
Ajax执行顺序流程及回调问题分析
2012/12/10 Javascript
Jquery读取URL参数小例子
2013/08/30 Javascript
JavaScript时间转换处理函数
2015/04/14 Javascript
JavaScript基本数据类型及值类型和引用类型
2015/08/25 Javascript
详解JS中Array对象扩展与String对象扩展
2016/01/07 Javascript
实例讲解使用原生JavaScript处理AJAX请求的方法
2016/05/10 Javascript
实现easyui的datagrid导出为excel的示例代码
2016/11/10 Javascript
JS比较两个数值的大小实例
2016/11/25 Javascript
AngularJS中的缓存使用
2017/01/11 Javascript
js输入框使用正则表达式校验输入内容的实例
2017/02/12 Javascript
深入解析Vue 组件命名那些事
2017/07/18 Javascript
JavaScript DOM元素常见操作详解【添加、删除、修改等】
2018/05/09 Javascript
webpack.DefinePlugin与cross-env区别详解
2020/02/23 Javascript
antd form表单数据回显操作
2020/11/02 Javascript
在Python中使用NLTK库实现对词干的提取的教程
2015/04/08 Python
批量获取及验证HTTP代理的Python脚本
2017/04/23 Python
利用Python操作消息队列RabbitMQ的方法教程
2017/07/19 Python
详解Python字符串切片
2019/05/20 Python
使用TensorFlow搭建一个全连接神经网络教程
2020/02/06 Python
Python Handler处理器和自定义Opener原理详解
2020/03/05 Python
带你学习Python如何实现回归树模型
2020/07/16 Python
Python unittest生成测试报告过程解析
2020/09/08 Python
Django中ORM的基本使用教程
2020/12/22 Python
Django实现简单的分页功能
2021/02/22 Python
倩碧香港官方网站:Clinique香港
2017/11/13 全球购物
公司法人授权委托书范本
2014/09/12 职场文书
施工安全协议书范本
2014/09/26 职场文书
交通安全月活动总结
2015/05/08 职场文书
2016秋季幼儿园开学寄语
2015/12/03 职场文书
2016廉政教育学习心得体会
2016/01/25 职场文书
靠谱准确的求职信
2019/04/02 职场文书
Django实现聊天机器人
2021/05/31 Python