Ajax是一个技术的名称, 而以前我们具体使用的是axios.js
插件来发送请求 ,但是其实axios.js也是一个库, 内部是原生JS代码, 实际它是对原生的代码进行了封装。
Ajax如果用原生JS实现, 需要使用window提供的一个构造函数, 叫XMLHttpRequest
使用格式
// 1. 创建一个xhr对象 let xhr = new XMLHttpRequest() // 2. 设置请求方式和请求地址 xhr.open(请求方式, 请求地址) // 3. 发送请求 xhr.send() // 4. 监听load(请求成功)事件 ==> 可以获取响应数据 xhr.addEventListener('load', function() { console.log(xhr.response) // 服务器返回的数据 })
Ajax_原生query传参
// 目标: 请求辽宁省下所有城市列表 let xhr = new XMLHttpRequest() // 复习: 之前说过query查询参数要携带在url?后面 // 格式: 参数名=值&参数名=值 xhr.open('GET', `http://ajax-api.itheima.net/api/city?pname=辽宁省`) xhr.send() xhr.addEventListener('load', function () { let result = JSON.parse(xhr.response) console.log(result); })
原生post
// 1. 创建一个xhr对象 let xhr = new XMLHttpRequest() // 2. 设置请求方式和请求地址 xhr.open(请求方式, 请求地址) // 3. 发送请求 // 请求体 xhr.send(请求体) // 4. 监听load(请求成功)事件 ==> 可以获取响应数据 xhr.addEventListener('load', function() { console.log(xhr.response) // 服务器返回的数据 })
\1. 请求体内容类型有哪三种?
键值对字符串
JSON字符串
表单数据FormData
同步异步
<script src="https://cdn.jsdelivr.net/npm/axios@0.27.2/dist/axios.min.js"></script> <script> console.log(1) if (true) { console.log(2); } else { console.log(3); } setTimeout(() => { console.log(4); }, 1000) const fn = () => { console.log(5); } for (let i = 0; i < 3; i++) { console.log(6); } console.log(7); fn() document.addEventListener('click', () => { console.log(8); }) axios({ url: 'http://ajax-api.itheima.net/api/province', method: 'GET' }).then(() => { console.log(9); }) console.log(10); </script>
打印结果是1 2 666 7 5 10 9 4
总结
同步代码: 执行顺序和书写顺序一致
异步代码: 不是立即执行的,执行顺序和书写顺序不一致。
js中典型的异步代码有:
-
定时器:setTimeout,setInterval
-
Ajax
-
dom事件
回调函数
是自己定义的函数,但不是自己调用的
典型特点:把一个函数当成实参传递, 将来特定的时机调用, 这个函数体就叫回调函数 。
回调地狱概念
在回调函数内, 再嵌套回调函数, 一直嵌套下去形成了回调地狱
实例
// 目标: 获取所有省市区数据, 随便获取 // 1. 获取所有省份列表 axios.get('http://ajax-api.itheima.net/api/province').then(res => { // 2. 获取某个省, 对应的城市列表 let pname = res.data.data[5]; axios.get(`http://ajax-api.itheima.net/api/city?pname=${pname}`).then(res => { // 3. 获取某个市, 对应的地区列表 let cname = res.data.data[0] axios.get(`http://ajax-api.itheima.net/api/area?pname=${pname}&cname=${cname}`).then(res => { console.log(res); }) }) })
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的执行
-
(pending: 准备; resolved(或者fulfilled) 成功; rejected: 失败
准备:new实例化后, Promise对象(pending准备状态)
成功:当Promise内代码执行了resolve, 会导致所在的Promise对象 变成 fulfilled成功状态
失败:当Promise内代码执行了reject, 会导致所在的Promise对象 变成 rejected失败状态
Promise_三种状态和值
(pending: 准备; resolved(或者fulfilled) 成功; rejected: 失败
准备:new实例化后, Promise对象(pending准备状态)
成功:当Promise内代码执行了resolve, 会导致所在的Promise对象 变成 fulfilled成功状态
失败:当Promise内代码执行了reject, 会导致所在的Promise对象 变成 rejected失败状态
使用promise改造回调函数
let ajax = function() { return new Promise((resolve,reject)=>{ var xhr = new XMLHttpRequest(); xhr.open('get','http://httpbin.org/ip') xhr.onload = function() { resolve(xhr.responseText) } xhr.onerror = function (){ reject('请求接口错误') } xhr.send() }) } ajax().then(res =>{ console.log(res) }).catch(err =>{ console.log(err) })
then的格式及执行逻辑
作用
then方法的作用是为Promise对象添加状态改变时的回调函数。
下面从其调用格式,执行逻辑及返回值三个方面来介绍
它有两个参数,每个参数都是函数。 第二个参数是可选的。
-
第一个参数是resolved状态的回调函数。当p的状态从pending变成了resolved,函数1会执行。
-
第二个参数是rejected状态的回调函数。 当p的状态从pending变成了rejected,函数2会执行。
// p 是一个promise对象 p.then(函数1[,函数2])
then的返回值
var p1 = new Promise(()=>{}); var p2 = p1.then(function f_ok(){}, function f_err(){}); // p2也是一个promise对象。 console.log(p1 === p2); // false
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就是这个错误对象。
-
catch的返回值
catch的返回值仍是一个promise对象,确定它的值的方式与then(null,(errVal)=>{ })的方式一致。
p.then()的返回值是一个新的promsie对象
Promise的静态方法_all
// 目标: 讲解Promise的all方法 // 静态(类)方法: 直接用Promise类来调用 // 1. Promise.all() // 作用: 合并多个Promise对象, 等待所有成功后, 返回结果 // 语法: Promise.all([promise对象1, promise对象2, ...]).then() // 特点: 返回最终结果是个数组, 值是按顺序对应小Promise对象的成功结果 // 注意: 如果有1个Promise失败, 则整个Promise对象则失败 let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功1') }, 2000) }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功2') }, 2000) }) let p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功3') }, 2000) }) Promise.all([p1, p2, p3]).then(res => { console.log(res); })
Promise的静态方法_race
// 目标: 讲解Promise的race方法 // 静态(类)方法: 直接用Promise类来调用 // 1. Promise.race() - 赛跑机制 // 作用: 发起并行多个Promise对象, 等待只要任何一个有结果(成功|失败), 返回结果执行then // 语法: Promise.race([promise对象1, promise对象2, ...]).then() // 特点: 返回第一个有结果的promise对象的结果 let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功1') }, 2000) }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功2') }, 2000) }) let p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功3') }, 2000) }) Promise.race([p1, p2, p3]).then(res => { console.log(res); })
Promise的静态方法resolve和reject
const p = Promise.resolve(值)
const p = Promise.reject(值)