深入理解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的无刷新分页技术
Jun 11 Javascript
Javascript 页面模板化很多人没有使用过的方法
Jun 05 Javascript
nullJavascript中创建对象的五种方法实例
May 07 Javascript
JavaScript实现时间倒计时跳转(推荐)
Jun 28 Javascript
React Native实现简单的登录功能(推荐)
Sep 19 Javascript
jQuery下拉菜单的实现代码
Nov 03 Javascript
js鼠标跟随运动效果
Mar 11 Javascript
ES6新数据结构Map功能与用法示例
Mar 31 Javascript
vue父子组件的嵌套的示例代码
Sep 08 Javascript
Angular父子组件通过服务传参的示例方法
Oct 31 Javascript
Angular使用Restful的增删改
Dec 28 Javascript
微信小程序引入模块中wxml、wxss、js的方法示例
Aug 09 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
地摊中国 - 珍藏老照片
2020/08/18 杂记
服务器端解压缩zip的脚本
2006/12/22 PHP
初学CAKEPHP 基础教程
2009/11/02 PHP
PHP中的数组处理函数实例总结
2016/01/09 PHP
Yii基于CActiveForm的Ajax数据验证用法示例
2016/07/14 PHP
PHP去除字符串最后一个字符的三种方法实例
2017/03/01 PHP
PHP判断是否微信访问的方法示例
2019/03/27 PHP
JavaScript与DropDownList 区别分析
2010/01/01 Javascript
firefox事件处理之自动查找event的函数(用于onclick=foo())
2010/08/05 Javascript
jQuery1.6 正式版发布并提供下载
2011/05/05 Javascript
不使用XMLHttpRequest实现异步加载 Iframe和script
2012/10/29 Javascript
jQuery.buildFragment使用方法及思路分析
2013/01/07 Javascript
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
JS与C#编码解码
2013/12/03 Javascript
使用原生js写的一个简单slider
2014/04/29 Javascript
JS组件Bootstrap按钮组与下拉按钮详解
2016/05/10 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
2016/06/20 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
2016/11/16 Javascript
js编写简单的计时器功能
2017/07/15 Javascript
jQuery中过滤器的基本用法示例
2017/10/11 jQuery
JavaScript中filter的用法实例分析
2019/02/27 Javascript
JS实现的碰撞检测与周期移动完整示例
2019/09/02 Javascript
jquery实现聊天机器人
2020/02/08 jQuery
python去除空格和换行符的实现方法(推荐)
2017/01/04 Python
python实现淘宝秒杀聚划算抢购自动提醒源码
2020/06/23 Python
Python基于递归算法实现的汉诺塔与Fibonacci数列示例
2018/04/18 Python
Python实现的txt文件去重功能示例
2018/07/07 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
2019/06/17 Python
韩国休闲女装品牌网站:ANAIS
2016/08/24 全球购物
香港优质食材和美酒专门店:FoodWise
2017/09/01 全球购物
委托书如何写
2014/08/30 职场文书
学会掌握自己命运的十条黄金法则:
2019/08/08 职场文书
Vue3.0写自定义指令的简单步骤记录
2021/06/27 Vue.js
springboot 自定义配置 解决Boolean属性不生效
2022/03/18 Java/Android
springboot实现string转json json里面带数组
2022/06/16 Java/Android
SQL bool盲注和时间盲注详解
2022/07/23 SQL Server