_XHR和Promise


Ajax是一个技术的名称, 而以前我们具体使用的是axios.js插件来发送请求 ,但是其实axios.js也是一个库, 内部是原生JS代码, 实际它是对原生的代码进行了封装。

今天我们就来解开神秘的面纱

Ajax如果用原生JS实现, 需要使用window提供的一个构造函数, 叫XMLHttpRequest
XMLHttpRequest
使用格式
// 1. 创建一个xhr对象
let xhr = new XMLHttpRequest()

// 2. 设置请求方式和请求地址
xhr.open(请求方式, 请求地址)

// 3. 发送请求
xhr.send()

// 4. 监听load(请求成功)事件 ==> 可以获取响应数据
xhr.addEventListener('load', function() {
console.log(xhr.response) // 服务器返回的数据
})
 

// 请求省份名字列表

// 接口地址: http://ajax-api.itheima.net/api/province

// 请求方式:GET

// 原生Ajax编写↓

// 1.创建一个xhr对象

let xhr = new XMLHttpRequest()

// 2.设置请求方式和请求地址 xhr.open("请求方式", "请求地址")

xhr.open('GET', 'http://ajax-api.itheima.net/api/province')

// 3.发送请求

xhr.send()

// 4.监听load(请求成功)事件 ==> 可以获取响应数据

xhr.addEventListener('load', function () {

console.log(xhr.response) // 响应体数据

// 知识点: 把JSON格式字符串 ==> 转成JS数据类型

// 语法: JSON.parse(JSON字符串)

// 返回值: JS数据类型

let result = JSON.parse(xhr.response)

console.log(result);

})


代码运行流程

目标:了解原生AJAX代码

主要的4个实现步骤:

LET XHR - NEW XMLHTTPREQUEST()

创建XHR对象

XHR.OPEN('GET','HTTP://AJAX-API.ITHEIMA.NET/API/PROVINCE"

调用XHR.OPEN()函数配置

请求

调用XHR.SEND()函数发出

XHR.SEND()

服务器

监听LOAD事件等待结果

XHR.ADDEVENTLISTENER('LOAD', FUNCTION

CONSOLE.LOG(XHR.RESPONSE) // 响应体数

向应体数据

LET RESULT JSON.PARSE(XHR.RESPONSE

响应

CONSOLE.LOG(RESULT);

子)

客户端


小结

1. Ajax原理底层依靠一个构造函数
XMLHttpRequest

02Ajax_原生query传参

目标
了解Ajax原生传参使用
讲解

新建Ajax_原生传参.html


小结
1. 原生Ajax如何传递查询参数?
在url?后面拼接查询参数

03Ajax_原生POST

目标

了解原生POST请求和请求体使用
格式
// 1. 创建一个xhr对象
let xhr = new XMLHttpRequest()

// 2. 设置请求方式和请求地址
xhr.open(请求方式, 请求地址)

// 3. 发送请求
// 请求体
xhr.send(请求体)

// 4. 监听load(请求成功)事件 ==> 可以获取响应数据
xhr.addEventListener('load', function() {
console.log(xhr.response) // 服务器返回的数据
})

示例

新建Ajax_原生POST.html, 请求POST测试接口

问题:发现后端并没有解析到我们的参数, 通过后台提示和Network检查, 我们请求头Content-Type的值不对

解决: 之前我们使用axios会自动携带Content-Type内容请求头, 而原生的ajax就需要自己携带啦!

落地完整代码


小结
1. 请求体内容类型有哪三种?
键值对字符串
JSON字符串
表单数据FormData

2. 使用axios时,自带了请求头的类型

04-概念_同步异步
目标
●掌握哪些是同步代码
●掌握哪些是异步代码
讲解
请先阅读如下代码的执行顺序并说出打印结果

2 打印的结果是

同步和异步
同步代码: 执行顺序和书写顺序一致
异步代码: 不是立即执行的,执行顺序和书写顺序不一致。

js中典型的异步代码有:
●定时器:setTimeout,setInterval
●Ajax
●dom事件

小结

1 JS中都有哪些异步代码?
●定时器, Ajax, 事件

05-概念_回调函数

目标

掌握回调函数的使用和执行过程,理解它和异步的关系

现象
发现前面异步的代码, 都有一个函数体, 这个函数体里代码都是等待这个异步任务有结果后执行

SETTIMEOUT( )

CONSOLE.LOG(4);

1000)



回调函数
是自己定义的函数,但不是自己调用的
典型特点:把一个函数当成实参传递, 将来特定的时机调用, 这个函数体就叫回调函数 。


我们之前接触的回调函数

1arr. forEach(() => {}), map, filter.....
2addEventlistener('click', () => {} )

小结

1 什么是回调函数?
●把一个函数当做实参传递, 将来特定的时机调用, 这个函数体就叫回调函数

06-概念_回调地狱
目标
理解的回调地狱的概念
示例
调用接口,请求第6个省的第1个市下的地区列表
特点:
1发多次ajax请求
2后一次请求要依赖上一次请求的结果

这里我们以一个, 请求省市区列表, 最终获取地区列表为例,  来体验下回调地狱, 直接复制代码查看

上面的代码就出现了回调地狱
概念: 在回调函数内, 再嵌套回调函数, 一直嵌套下去形成了回调地狱

小结
1. 什么是回调地狱?
在回调函数内, 再嵌套回调函数, 一直嵌套下去形成了回调地狱
07-Promise_基本语法
目标
掌握Promise相关语法使用

Promise
它是一个ES6提出一个新语法,用来优化异步代码的写法。
●在前端领域是我们必须要会的一个内容
●后续的课程中也会多次使用
promise:承诺。
●生活中.它是用来表述 对将来要发生的事情的肯定。 例如 : 高中生说,老师,我会考上一所好大学的;销售员说,老板,我一定会签下大单的;程序员说,老妈,我过年一定会带个女朋友回来的。
●在ES6中,它是新增的构造器(Array, Object, Promise),用来优化实现异步操作。在没有它之前,javascript中的异步处理,大多是利用回调函数来实现的。典型的几种如下:(1)setTimeout (2)ajax 现在有了promise,就可以对这些异步操作进行改写了。
经典格式

let p1 = new Promise((resolve, reject) => {
// resolve和reject是Promise内提供的2个函数, 用于回调返回结果到外面
resolve(成功结果) // 触发.then()小括号里函数体执行
reject(失败结果) // 触发.catch()小括号里函数体执行
})

p1.then((成功结果变量名) => {

}).catch((失败结果变量名) => {

}).finally(()=>{
// 一定会执行的代码
})

●resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”,触发.then的执行
●reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”,触发.catch的执行
示例代码

新建html文件, 来熟悉下Promise的相关语法

图示

resolve(值1) 

then 

catch 

new Promise((resolve, reject)=>{  resolve(值1) })

.then(res=>{  console.log(res) })

.catch(err=>{})

.finally()

值1​

finally 

reject(值1) 

then 

catch 

new Promise((resolve, reject)=>{  reject(值1) })

.then(res  =>  { })

.catch(err  => { })

.finally()

值1​

finally 



小结

1. new 一个 Promise的格式是?
const p = new Promise((resolve, reject)=>{}) p.then().catch().finally()
2. 对象内的resolve和reject函数作用?
回调外部的then/catch, 传递成功/失败的动作和结果


08-Promise_三种状态和值
目标
掌握Promise的三种状态和值
三种状态
(pending: 准备; resolved(或者fulfilled) 成功; rejected: 失败

准备:new实例化后, Promise对象(pending准备状态)
成功:当Promise内代码执行了resolve, 会导致所在的Promise对象 变成 fulfilled成功状态
失败:当Promise内代码执行了reject, 会导致所在的Promise对象 变成 rejected失败状态

FULFILLED

成功

PENDING

默认

REJECTED

失败


状态的变化不可逆



resolve(值),这个值会自动传递给then
reject(值),这个值会自动传递给catch
示例代码


小结
1. Promise对象有几种状态?
pending, fulfilled, rejected
2. Promise对象的状态如何切换?
刚创建会立刻执行new Promise函数内代码, 此时为pending准备状态
当Promise对象内异步代码有结果触发resolve, 会导致Promise对象状态为fulfilled兑现成功状态
当Promise对象内异步代码有结果触发reject, 会导致Promise对象状态为rejected失败状态, 拒绝兑现承诺


09-使用promise改造回调函数
下面我们回到具体的问题:如何对现有的,通过回调函数来实现异步操作的代码进行改写。
基本套路
第一步:建立模板函数。这里的模板函数是指固定的套路:写一个空函数,在函数体中new 一个promise对象,并返回。
第二步:把异步功能写入构造函数中,根据实际来决定是否调用resolve,reject。
第三步:调用函数。通过fnName().then().catch() 结构来调用这个函数。

示例: ajax原回调函数的写法
改写之后
这里用到的接口http://httpbin.org/ip是从http.org 上访问的。


10小小一道面试题
代码填空,并完成指定功能。
目标 是让sleep 的功能与setTimeout一样:就是等2000毫秒之后再执行then中的回调函数
参考代码如下:

解锁


11-then的格式及执行逻辑
目标
掌握then方法的使用;
作用
then方法的作用是为Promise对象添加状态改变时的回调函数。
下面从其调用格式,执行逻辑及返回值三个方面来介绍
then的调用格式
它有两个参数,每个参数都是函数。 第二个参数是可选的。
如下:
它的两个参数都是函数。
●第一个参数是resolved状态的回调函数。当p的状态从pending变成了resolved,函数1会执行。
●第二个参数是rejected状态的回调函数。 当p的状态从pending变成了rejected,函数2会执行。
其中第二个参数是可选的,如果只写一个参数的话就是如下:
promise对象.then(函数1)
执行逻辑
以如下代码为例
它的两个参数都是函数,其执行逻辑是:
●如果promise对象的状态是resolved,则then()会执行第一个函数,并传入当前的PromiseValue(即上面的val1);
●如果promise对象的状态是rejected,则then()会执行第二个函数,并传入当前的PromiseValue(即上面的val2);
●特别地,如果promise对象的状态是rejected,且此时then方法并没有设置第二个参数,就会向外抛出一个错误,错误的提示大约是Uncaught (in promise)。
如下是图示

NEW PROMISE((RESOLVE,REJECT)->{

NEW PROMISE((RESOLVE,REJECT)->{

VAR

VAR

RESOLVE(VAL1);

RESOLVE(VAL1)

// OR RE JECT(VAL2)

REJECT(VAL2)

子)

子)

P.THEN(

THEN(

OKVAL

OKVAL>{

CONSOLE.INFO("成功");

CONSOLE.INFO("成功");

CONSOLE.LOG(OKVALUE);

CONSOLE.LOG(OKVALUE);

ERRVAL>{

ERRVAL>{

CONSOLE.INFO("失败");

CONSOLE.INFO("失败");

CONSOLE.LOG(ERRVALUE)

CONSOLE.LOG(ERRVALUE)


示例代码1
执行输出结果是:then,ok,1
示例代码2
执行输出结果是:then,err,2
12-then的返回值(难点)
then()方法的返回值也是一个promise对象,但是要注意的是它的返回值是一个新的promise对象,与调用then方法的并不是同一个对象。

看如下代码:
如上代码可以说明p1.then()的结果是一个与p1不同的promise对象。换句话说,then()会封装一个全新的promise对象p2。那既然 p2也是一个promise对象,那么,p2的状态(promiseStatus)和值(promiseValue)分别是什么?
p2的状态及promiseValue如何确定?
p2的状态及promiseValue按如下规则来确定
●如果p1的状态是pending,则p2的状态也是pending。
●如果p1的状态是resolved,then()会去执行f_ok,则p2的状态由f_ok的返回值决定。
○如果f_ok返回值不是promise对象,则p2的状态是resolved,且p2的promiseValue就是f_ok函数的return值。
○如果f_ok返回值是一个promise对象,则p2的状态及promiseValue以这个promise对象为准。
○如果f_ok这个函数内部发生了错误(或者是用户主动抛出错误),则p2的状态是rejected,且p2的promiseValue就是这个错误对象。
●如果p1的状态是rejected,then()会去执行f_err,则p2的状态由f_err的返回值决定。
○如果f_err返回值不是promise对象,则p2的状态是resolved,且p2的promiseValue就是f_err函数的return值。
○如果f_err返回值是一个promise对象,则p2的状态及promiseValue以这个promise对象为准。
○如果f_err这个函数内部发生了错误(或者是用户主动抛出错误),则p2的状态是rejected,且p2的promiseValue就是这个错误对象。
练习1
练习2
特殊地,如果f_ok()中并没有return语句,则相当于是 return undefined。
练习3
练习4
练习5
练习6
13-catch的格式及用法
catch 是 then(null, reject)的别名
catch()的格式及用法
Promise.prototype.catch 是 Promise.prototype.then(null, reject)的别名,用于指定当promise对象的状态从pending变成rejected的回调函数 。
单独使用catch没有什么意义,它一般与then一块使用。如下:
catch的返回值
catch的返回值仍是一个promise对象,确定它的值的方式与then(null,(errVal)=>{ })的方式一致。

14Promise_链式调用
目标

掌握Promise的链式调用
p.then()的返回值是一个新的promsie对象

编写代码进行讲解

小结

1 then里return的Promise对象结果, 交到哪里执行?
●下一个then接收成功结果
15Promise_解决回调地狱
目标
使用Promise来解决回调地狱
基础代码
讲解

1 新建html文件, 用axios方法原地返回Promise对象特性
2 用.then()里return Promise对象结果会被链式调用下一个then接收特性
把回调函数嵌套的写法, 变成链式调用then的形式

小结
1. Promise是如何解决回调地狱的问题的?
根据.then的链式调用把Promise对象串联起来
16Promise的静态方法_all
目标
能说出Promise.all方法的作用
Promise的all方法



小结

1 Promise.all方法有什么作用?
●合并并发多个Promise对象, 等待所有人成功, 按顺序接收结果

17Promise的静态方法_race
目标
能说出Promise.race方法的作用
讲解

1 讲解Promise的race方法



小结
1. Promise.race方法有什么作用?
合并并发多个Promise对象, 接收最先成功的结果

18Promise的静态方法resolve和reject

目标
能说出Promise的静态方法resolve和reject方法作用
Promise.resolve
作用
创建一个状态为resolved的promise对象,并指定其值。或者理解为:把值转成Promise对象,并设置状态和值。

格式
Promise.reject
作用
创建一个状态为rejected的promise对象。
格式

小结
1. Promise.resolve和Promise.reject有什么作用?
创建一个状态为resolved, rejected的promise对象,并指定其值


19案例_封装Ajax函数

目标
了解封装原生Ajax请求的代码
讲解
新建html文件, 封装itheimaAxios函数。


小结

1 promise的作用在于改写原来需要回调函数才实现的异步操作。

20案例-分类导航

目标

● 完成分类导航案例

个护

严选

数码

服饰

美食

居家

运动

母婴

杂项



讲解

新建html, 在这个基础上编写

分析思路和数据, 进行铺设



小结

1 如何同时发送多个请求, 并按顺序接收结果?
●使用Promise.all方法

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值