深入理解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 设置文本框中焦点的位置
Nov 20 Javascript
javascript下4个跨浏览器必备的函数
Mar 07 Javascript
jquery图片放大镜功能的实例代码
Mar 26 Javascript
javascript将数字转换整数金额大写的方法
Jan 27 Javascript
有效提高JavaScript执行效率的几点知识
Jan 31 Javascript
AngularJS模块管理问题的非常规处理方法
Apr 29 Javascript
JS中实现函数return多个返回值的实例
Feb 21 Javascript
jquery中绑定事件的异同
Feb 28 Javascript
node.js实现回调的方法示例
Mar 01 Javascript
jquery操作ul的一些操作笔记整理(干货)
Aug 31 jQuery
浅谈Vue 初始化性能优化
Aug 31 Javascript
js实现九宫格抽奖
Mar 19 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
详解PHP5.6.30与Apache2.4.x配置
2017/06/02 PHP
jQuery+PHP实现图片上传并提交功能
2020/07/27 PHP
jQuery ctrl+Enter shift+Enter实现代码
2010/02/07 Javascript
Jqyery中同等与js中windows.onload的应用
2011/05/10 Javascript
一个页面放2段图片滚动代码出现冲突的问题如何解决
2012/12/21 Javascript
JavaScript中用于生成随机数的Math.random()方法
2015/06/15 Javascript
jQuery实现简单的文件上传进度条效果
2020/03/26 Javascript
js实现将选中内容分享到新浪或腾讯微博
2015/12/16 Javascript
Bootstrap模态框插件使用详解
2017/05/11 Javascript
解决Vue2.x父组件与子组件之间的双向绑定问题
2018/03/06 Javascript
浅析JS中回调函数及用法
2018/07/25 Javascript
如何使用electron-builder及electron-updater给项目配置自动更新
2018/12/24 Javascript
实例讲解vue源码架构
2019/01/24 Javascript
Element ui 下拉多选时新增一个选择所有的选项
2019/08/21 Javascript
[02:41]2015国际邀请赛中国区预选赛观战指南
2015/05/20 DOTA
使用Python写个小监控
2016/01/27 Python
深入解析Python中函数的参数与作用域
2016/03/20 Python
Python守护进程和脚本单例运行详解
2017/01/06 Python
python爬虫获取京东手机图片的图文教程
2017/12/29 Python
1 行 Python 代码快速实现 FTP 服务器
2018/01/25 Python
Python爬豆瓣电影实例
2018/02/23 Python
pyhton列表转换为数组的实例
2018/04/04 Python
基于tensorflow加载部分层的方法
2018/07/26 Python
python列表使用实现名字管理系统
2019/01/30 Python
python手写均值滤波
2020/02/19 Python
Keras实现DenseNet结构操作
2020/07/06 Python
python实现AHP算法的方法实例(层次分析法)
2020/09/09 Python
利用CSS3的transition属性实现滑动效果
2015/08/05 HTML / CSS
护理学应聘自荐书范文
2014/02/05 职场文书
民生工程实施方案
2014/03/22 职场文书
家长通知书家长评语
2014/04/17 职场文书
妇女工作先进事迹
2014/08/17 职场文书
团员自我评价范文
2015/03/10 职场文书
创业计划书之美容店
2019/09/16 职场文书
Golang二维切片初始化的实现
2021/04/08 Golang
Java时间工具类Date的常用处理方法
2022/05/25 Java/Android