Promise

1.Promise基本介绍

Promise是异步编程的一种解决方案,可以解决传统Ajax回调函数嵌套问题。

  1. 传统的Ajax异步调用在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的Callback Hell
  2. 为了解决上述的问题,Promise对象应运而生,在EMCAScript 2015当中已经成为标准,Promise也是ES6的新特性
  3. Promise是异步编程的一种解决方案
  4. 从语法上说,Promise是一个对象,从它可以获取异步操作的消息

2.Promise应用实例

2.1需求分析/图解

  1. 需求:演示promise异步请求使用

  2. 执行效果:

2.2代码实现

使用json文件模拟数据库表数据

monster.json

{
"id": 1,
"name": "黑山老妖"
}

monster_detail_1.json

{
"id": 1,
"address": "黑山洞",
"skill": "翻江倒海",
"age": 500,
"gfid": 2
}

monster_gf_2.json

{
"name": "狐狸精",
"age": 100
}

2.2.1jquery-ajax实现多次ajax请求

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jquery-ajax多次请求</title>
<!--引入jquery-->
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//jquery发出ajax的方式
$.ajax({
url: "data/monster.json",
success(resultData) {//第一次ajax成功的回调函数
console.log("第一次ajax请求 monster 基本信息=", resultData);
//发出第二次ajax请求
$.ajax({
//第二次ajax请求的url根据第一次的结果来改变
url: `data/monster_detail_${resultData.id}.json`,
success(resultData) {//第二次ajax成功的回调函数
console.log("第二次ajax请求 monster 详细信息=", resultData);
},
error(err) {
console.log("第二次ajax请求出现异常=", err);
}
})
},
error(err) {
console.log("第一次ajax请求出现异常=", err);
}
})
</script>
</head>
<body> </body>
</html>

使用jquery-ajax的方式容易出现回调函数嵌套(Callback Hell),如果发出的是多次ajax请求,那么嵌套的层数将会变得非常多,代码不易读。这种写法冗余度高,代码可维护性低。

2.2.2promise对象实现多次ajax请求

首先创建一个Promise对象,在该对象内传入一个箭头函数,箭头函数内进行ajax请求。Promise对象的箭头函数传入了两个方法作为参数(命名随意),这里的resolve方法是ajax请求成功后调用的函数,reject方法是ajax请求失败后调用的函数。不同于jquery的回调嵌套,在ajax请求成功的success方法中会调用resolve(),并且把第一次ajax请求获得的数据传入该方法。

resolve方法会跳到Promise对象的then()方法,then方法中可以继续使用$.ajax()去进行第二次ajax请求。在then方法中,又创建了一个Promise对象,该对象和之前的Promise对象中的业务逻辑相似,不同的是可以通过上一次的resolve方法,拿到第一次ajax请求返回的数据,然后根据数据进行第二次的ajax请求.......在第二次的ajax请求中,又可以获取第二次ajax请求返回的数据,然后调用这次Promise对象的resolve(),将新的数据传给这次Promise对象的then()方法.....

即,第二次ajax请求的resolve方法又会跳到Promise对象的then()方法........以此类推。

整个过程形成了一个链式的调用。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用promise完成多次ajax请求</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//先请求到monster.json
//1.创建Promise对象
//2.构造函数需要传入一个箭头函数
//3.(resolve, reject)参数列表,resolve:如果请求成功,调用resolve函数
// reject:如果请求失败,调用reject函数
//4.箭头函数体内仍然是通过jquery发出ajax
let promise = new Promise((resolve, reject) => {
//发出ajax请求
$.ajax({
url: "data/monster.json",
success(resultData) {//第一次ajax请求成功的回调函数
console.log("Promise发出的第一次ajax请求,返回的monster基本信息=", resultData);
resolve(resultData);
},
error(err) {
//console.log("Promise第一次异步请求出现异常=", err);
reject(err);
}
})
}); //这里我们可以继续编写第一次请求成功之后的业务
//仍然使用箭头函数
promise.then((resultData) => {
//这里可以继续发出请求
return new Promise((resolve, reject) => {
$.ajax({
url: `data/monster_detail_${resultData.id}.json`,
success(resultData) {//第二次ajax请求成功的回调函数
console.log("Promise发出的第二次ajax请求,返回的monster详细信息=", resultData);
//可以继续进行下一次的请求
resolve(resultData);
},
error(err) {
//console.log("Promise第二次异步请求出现异常=", err);
reject(err);
}
})
})
}).then((resultData) => {
console.log("promise.then().then(),resultDate", resultData);
//这里可以继续发出第三次ajax请求....
return new Promise(((resolve, reject) => {
$.ajax({
url: `data/monster_gf_${resultData.gfid}.json`,
success(resultData) {//第二次ajax请求成功的回调函数
console.log("Promise发出的第三次ajax请求,返回的monster gf信息=", resultData);
//可以继续进行下一次的请求
//resolve(resultDate);
},
error(err) {
//console.log("Promise第三次次异步请求出现异常=", err);
reject(err);
}
})
})) }).catch((err) => {//这里可以对多次ajax请求的异常进行处理
console.log("promise异步请求异常=", err);
})
</script>
</head>
<body> </body>
</html>

2.2.3promise代码重排

虽然在2.2.2中使用promise实现了多次ajax请求,解决了jquery-ajax的嵌套回调问题,但是代码仍然显得臃肿。创建Promise对象和进行ajax请求的代码是重复的,因此可以进行封装,代码重排,增强可读性。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise代码重排</title>
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
/**
* 这里我们将重复的代码封装,编写为get方法
* @param url ajax请求的资源
* @param data ajax请求携带的数据
* @returns {Promise<unknown>}
*/
function get(url, data) {
return new Promise(((resolve, reject) => {
$.ajax({
url: url,
data: data,
success(resultData) {
resolve(resultData);
},
error(err) {
reject(err);
}
})
}))
} //需求:完成
//1.先获取monster.json
//2.再获取monster_detail_1.json
//3.再获取monster_gf_2.json get("data/monster.json").then((resultData) => {
//第一次ajax请求成功后的处理代码
console.log("第1次ajax请求返回的数据=", resultData);
return get(`data/monster_detail_${resultData.id}.json`); }).then((resultData) => {
//第二次ajax请求成功后的处理代码
console.log("第2次ajax请求返回的数据=", resultData);
return get(`data/monster_gf_${resultData.gfid}.json`); }).then((resultData) => {
//第三次ajax请求成功后的处理代码
console.log("第3次ajax请求返回的数据=", resultData);
//如果还有就继续... }).catch(err => {
console.log("请求出现异常=", err)
}) </script>
</head>
<body> </body>
</html>

3.练习

分别使用Jquery-Ajax和Promise代码重排,完成如下功能,发出3次ajax请求,获取对应的数据,注意体会Promise发出多次Ajax请求的方便之处。

student_100.json

{
"id": 100,
"name": "jack",
"class_id": 10
}

class_10.json

{
"id": 10,
"name": "java工程师班级",
"student_num": 30,
"school_id": 9
}

school_9.json

{
"id": 9,
"name": "清华大学",
"address": "北京"
}

3.1jquery-ajax方式

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jquery-ajax</title>
<script type="text/javascript" src="../script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//第一次ajax请求
$.ajax({
url: "data/student_100.json",
success(resultData) {
console.log("第一次ajax请求=", resultData);
//第二次ajax请求
$.ajax({
url: `data/class_${resultData.class_id}.json`,
success(resultData) {
console.log("第二次ajax请求=", resultData);
//第三次ajax请求
$.ajax({
url: `data/school_${resultData.school_id}.json`,
success(resultData) {
console.log("第三次ajax请求=", resultData);
},
error(err) {
console.log("第三次ajax请求出现异常=", err);
}
})
},
error(err) {
console.log("第二次ajax请求出现异常=", err);
}
})
},
error(err) {
console.log("第一次ajax请求出现异常=", err);
}
})
</script>
</head>
<body> </body>
</html>

3.2Promise代码重排

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise代码重排</title>
<script type="text/javascript" src="../script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
//get方法也可以封装到js工具类,重复使用
function get(url, data) {
return new Promise(((resolve, reject) => {
$.ajax({
url: url,
data: data,
success(resultData) {
resolve(resultData);
},
error(err) {
reject(err);
}
})
}))
} //业务
get("data/student_100.json").then(resultData => {
console.log("第1次返回的数据=", resultData);
return get(`data/class_${resultData.class_id}.json`);
}).then(resultData => {
console.log("第2次返回的数据=", resultData);
return get(`data/school_${resultData.school_id}.json`);
}).then(resultData => {
console.log("第3次返回的数据=", resultData);
//如有需求可以继续请求...
}).catch(err => {
console.log("promise异步请求异常=", err)
})
</script>
</head>
<body> </body>
</html>

day02-Promise的更多相关文章

  1. Javascript - Promise学习笔记

    最近工作轻松了点,想起了以前总是看到的一个单词promise,于是耐心下来学习了一下.   一:Promise是什么?为什么会有这个东西? 首先说明,Promise是为了解决javascript异步编 ...

  2. 路由的Resolve机制(需要了解promise)

    angular的resovle机制,实际上是应用了promise,在进入特定的路由之前给我们一个做预处理的机会 1.在进入这个路由之前先懒加载对应的 .js $stateProvider .state ...

  3. angular2系列教程(七)Injectable、Promise、Interface、使用服务

    今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我 ...

  4. 闲话Promise机制

    Promise的诞生与Javascript中异步编程息息相关,js中异步编程主要指的是setTimout/setInterval.DOM事件机制.ajax,通过传入回调函数实现控制反转.异步编程为js ...

  5. 深入理解jQuery、Angular、node中的Promise

    最初遇到Promise是在jQuery中,在jQuery1.5版本中引入了Deferred Object,这个异步队列模块用于实现异步任务和回调函数的解耦.为ajax模块.队列模块.ready事件提供 ...

  6. Promise的前世今生和妙用技巧

    浏览器事件模型和回调机制 JavaScript作为单线程运行于浏览器之中,这是每本JavaScript教科书中都会被提到的.同时出于对UI线程操作的安全性考虑,JavaScript和UI线程也处于同一 ...

  7. JavaScript进阶之路——认识和使用Promise,重构你的Js代码

    一转眼,这2015年上半年就过去了,差不多一个月没有写博客了,"罪过罪过"啊~~.进入了七月份,也就意味着我们上半年苦逼的单身生活结束了,从此刻起,我们要打起十二分的精神,开始下半 ...

  8. 细说Promise

    一.前言 JavaScript是单线程的,固,一次只能执行一个任务,当有一个任务耗时很长时,后面的任务就必须等待.那么,有什么办法,可以解决这类问题呢?(抛开WebWorker不谈),那就是让代码异步 ...

  9. 浅谈Angular的 $q, defer, promise

    浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00  博客园-原创精华区 原文  http://www.cnblogs.com/big-snow/ ...

  10. angular学习笔记(二十八-附2)-$http,$resource中的promise对象

    下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource) ...

随机推荐

  1. Linux安装oracle 12C

    安装虚拟系统CentOS6.5,分配给至少1G的内存,其他条件适当高些,具体参考官方文档 环境准备 vim /etc/profileexport JAVA_HOME=/opt/jdk1.7.0_79e ...

  2. 云的安全组和网络ACL

    云的安全组和网络ACL 1.流量控制: 安全组是云服务器.数据库等实例级别的流量控制 ​ ACL是子网级别的流量控制 2.规则: 安全组和网络ACL都支持允许规则和拒绝规则 3.状态: 安全组有状态( ...

  3. 【做题笔记】CSP-S 往年试题

    题单 本文章正在持续更新-- [2021] 廊桥分配 题目 题面描述 所有飞机分为两类--国内区和国际区,两区廊桥数量互不干扰.每架飞机遵循"先到先得"的原则,优先选择编号最小的廊 ...

  4. JAVA学习前准备

    电脑常用快捷键 Ctrl+C:复制 Ctrl+V:粘贴 Ctrl+A:全选 Ctrl+X:剪切 Ctrl+Z:撤销 Ctrl+S:保存 Alt+F4:关闭窗口 Shift+delete:永久性删除文件 ...

  5. Mysql+Mycat+NFS+Rsync+LVS+DNS+IPtables综合实验

    1.环境准备 服务器 IP地址 作用 系统版本 Mysql-master eth0:10.0.0.58 主数据库 Rocky8.6 Mysql-slave1 eth0:10.0.0.68 备数据库 R ...

  6. javascript异步编程之generator(生成器函数)与asnyc/await语法糖

    Generator 异步方案 相比于传统回调函数的方式处理异步调用,Promise最大的优势就是可以链式调用解决回调嵌套的问题.但是这样写依然会有大量的回调函数,虽然他们之间没有嵌套,但是还是没有达到 ...

  7. 洛谷 P6573 [BalticOI 2017] Toll 题解

    Link 算是回归OI后第一道自己写的题(考CSP的时候可没回归) 写篇题解纪念一下 题目大意: \(n\) 个点,\(m\) 条单向边,每条边的两端点 \(x\),\(y\)必定满足 \(\left ...

  8. htaccess如何配置隐藏index.php文件

    <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On RewriteCond %{RE ...

  9. linux下进程的实际用户ID(有效组)和有效用户ID(有效组ID)

    实际用户ID(实际组ID):标识当前用户(所属组)是谁,当用户登陆时取自口令文件. 有效用户ID(有效组ID):用来决定我们(当前进程)对文件的访问权(即实际该进程的是以那个用户运行的). 一般情况下 ...

  10. C语言实验手册

    在三位整数(100~999)中寻找符合条件的整数,并以此从小到大存到数组当中,它既是完全平方数,又是两位数字相同,例如144,676等. #include<stdio.h> #includ ...