当前位置: 首页 > news >正文

AJAX和Promise

文章目录

  • AJAX
    • XMLHttpRequest
    • Axios使用
  • Promise
    • 基本语法
    • Promise的基本原理
    • 回调地狱问题
    • 封装简易Axios
    • 事件循环-EventLoop
    • Promise静态方法
      • Promise.resolve()
      • Promise.reject()
      • Promise.all()
      • Promise.allSettled()
      • Promise.race()
      • Promise.any()
      • Promise.try() (非标准,但常用)

AJAX

AJAX 是浏览器与服务器进行数据通信的技术,AJAX是异步的JavaScript和XML,就是使用XMLHttpRequest对象与服务器通信,它可以使用JSON、XML、HTML和text文本等格式发送和接收数据。AJAX最大特点是异步,可以不刷新页面的情况下与服务器通信,交换数据。

XMLHttpRequest

AJAX是基于XMLHttpRequest进行实现,以下是XMLHttpRequest的基本使用。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div class="myp"></div><script>// 1.创建XMLHttpRequest对象const xhr = new XMLHttpRequest()// 2.配置请求方法和urlxhr.open('GET', '')  // 3.配置监听loadend事件,接收响应结果xhr.addEventListener('loadend', () => {console.log(xhr.response);const data = JSON.parse(xhr.response)console.log(data.list.join('<br>'));document.querySelector('.myp').innerHTML = data.list.join('<br>')})// 4.发起请求xhr.send()</script>
</body>
</html>

Axios使用

Axios 是一个基于Promise的网络请求库,在现代前端开发中,Axios 已经成为事实上的标准,提供了更现代化、更强大的 HTTP 客户端功能。

<!-- axios库地址CDN -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>axios({url: '目标资源地址',method: '请求方法',params: { 参数名:}, // 查询参数data: {参数名:} // 提交数据
}).then(result => {console.log(result)
}).catch(error => {// 错误处理
})
</script>

Http请求方法

请求方法操作
GET获取数据
POST数据提交
PUT修改数据(全部)
DELETE删除数据
PATCH修改数据(部分)

form-serialize 插件
使用serialize函数,快速收集表单元素的值

<script src="./lib/form-serialize.js"></script>
<script>document.querySelector('.btn').addEventListener('click', () => {/*** 2. 使用serialize函数,快速收集表单元素的值* 参数1:要获取哪个表单的数据*  表单元素设置name属性,值会作为对象的属性名*  建议name属性的值,最好和接口文档参数名一致* 参数2:配置对象*  hash 设置获取数据结构*    - true:JS对象(推荐)一般请求体里提交给服务器*    - false: 查询字符串*  empty 设置是否获取空值*    - true: 获取空值(推荐)数据结构和标签结构一致*    - false:不获取空值*/const form = document.querySelector('.example-form')const data = serialize(form, { hash: true, empty: true })// const data = serialize(form, { hash: false, empty: true })// const data = serialize(form, { hash: true, empty: false })console.log(data)})
</script>

上传图片

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input type="file" class="upload"><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>document.querySelector('.upload').addEventListener('click', e => {console.log(e.target.files[0]);const fd = new FormData()fd.append('img', e.target.files[0])axios({url: '',method: 'post',data: fd})})</script>
</body>
</html>

Promise

基本语法

Promise对象用于表示一个异步操作的最终完成或失败及其结果值。基本语法:

// 1.创建Promise对象
const p = new Promise((resolve, reject) => {// 2.执行异步代码// 成功调用 resolve('模拟AJAX请求-成功结果')// 失败调用 reject(new Error('模拟AJAX请求-失败结果'))
})
// 3.获取结果
p.then(result => {// 成功
}).catch(error => {// 失败
})

Promise的基本原理

把“将来会得到的结果”封装成一个对象,并允许你现在就注册“成功/失败时要做什么”。换句话说,Promise是一个“未来值”的占位符 + 回调管理器。
以下是Promise的一个简易实现,用于理解Promise的核心设计思想。

function SimplePromise(executor) {let state = 'pending'; // 'pending' | 'fulfilled' | 'rejected'let value;             // 成功的值let reason;            // 失败的原因let onFulfilledCallbacks = [];let onRejectedCallbacks = [];const resolve = (val) => {if (state !== 'pending') return;state = 'fulfilled';value = val;onFulfilledCallbacks.forEach(cb => cb(value));};const reject = (err) => {if (state !== 'pending') return;state = 'rejected';reason = err;onRejectedCallbacks.forEach(cb => cb(reason));};try {executor(resolve, reject);} catch (e) {reject(e);}this.then = function(onFulfilled, onRejected) {return new SimplePromise((resolveNext, rejectNext) => {// 成功处理函数const handleFulfilled = (val) => {try {const result = onFulfilled(val);resolveNext(result);} catch (e) {rejectNext(e);}};// 失败处理函数const handleRejected = (err) => {try {const result = onRejected ? onRejected(err) : err;// 如果用户没传 onRejected,就继续抛出错误(错误冒泡)if (onRejected) {resolveNext(result); // 注意:catch 后返回的是成功值!} else {rejectNext(result);}} catch (e) {rejectNext(e);}};if (state === 'fulfilled') {handleFulfilled(value);} else if (state === 'rejected') {handleRejected(reason);} else {onFulfilledCallbacks.push(handleFulfilled);onRejectedCallbacks.push(handleRejected);}});};
}

async / await 是 JavaScript 中用于处理异步操作的语法糖,底层完全基于 Promise,await 本质上是 .then() 的语法糖,而 async 函数总是返回一个 Promise。

async function fetchData() {const res = await fetch('/api/data'); // 等待 Promise 完成const data = await res.json();return data; // 自动包装成 Promise
}// 调用
fetchData().then(data => console.log(data));

等价于

function fetchData() {return fetch('/api/data').then(res => res.json()).then(data => data); // 返回值自动被 Promise.resolve 包装
}

回调地狱问题

在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱,可读性差,异常无法获取,耦合性严重,牵一发动全身

 /*** 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中*/// 1. 获取默认第一个省份的名字axios({url: 'http://xxx/api/province'}).then(result => {const pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2. 获取默认第一个城市的名字axios({url: 'http://xxx/api/city', params: { pname }}).then(result => {const cname = result.data.list[0]document.querySelector('.city').innerHTML = cname// 3. 获取默认第一个地区的名字axios({url: 'http://xxx/api/area', params: { pname, cname }}).then(result => {console.log(result)const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName})})}).catch(error => {console.dir(error)})

使用Promise链式调用进行优化,可以使代码更加清晰。

    let pname = ''// 1. 得到-获取省份Promise对象axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2. 得到-获取城市Promise对象return axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})}).then(result => {const cname = result.data.list[0]document.querySelector('.city').innerHTML = cname// 3. 得到-获取地区Promise对象return axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})}).then(result => {console.log(result)const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName})

使用async和await语法,解决回调函数地狱
在async函数内,使用await关键字,获取Promise对象"成功状态"结果值
注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)

    // 1. 定义async修饰函数async function getData() {// 2. await等待Promise对象成功的结果const pObj = await axios({url: 'http://hmajax.itheima.net/api/province'})const pname = pObj.data.list[0]const cObj = await axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})const cname = cObj.data.list[0]const aObj = await axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})const areaName = aObj.data.list[0]document.querySelector('.province').innerHTML = pnamedocument.querySelector('.city').innerHTML = cnamedocument.querySelector('.area').innerHTML = areaName}getData()

封装简易Axios

使用Promise+XMLHttpRequest封装简易的axios

function myAxios(config) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()if(config.params) {const paramObj = new URLSearchParams(config.params)const queryStr = paramObj.toString()config.url += `?${queryStr}`}xhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', () => {if (xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})if(config.data) {xhr.setRequestHeader('Content-Type', 'application/json')xhr.send(JSON.stringify(data))} else {xhr.send()}})            
}
myAxios({url: ''
}).then(result => {console.log(result);
}).catch(err => {console.log(err);
})

事件循环-EventLoop

ES6 之后引入了 Promise 对象, 让 JS 引擎也可以发起异步任务
异步任务分为:

  • 宏任务:由浏览器环境执行的异步代码
  • 微任务:由 JS 引擎环境执行的异步代码,Promise对象.then()中的代码为微任务
    在这里插入图片描述

Promise静态方法

Promise.resolve()

创建一个立即解析的 Promise

// 使用值解析
Promise.resolve("成功").then(value => {console.log(value); // 输出: "成功"
});// 解析一个 Promise
const original = Promise.resolve("原始值");
const wrapped = Promise.resolve(original);
wrapped.then(value => {console.log(value); // 输出: "原始值"
});// 解析 thenable 对象
Promise.resolve({then(resolve, reject) {resolve("thenable 对象");}
}).then(value => {console.log(value); // 输出: "thenable 对象"
});

Promise.reject()

创建一个立即拒绝的 Promise

Promise.reject(new Error("操作失败")).catch(error => {console.error(error.message); // 输出: "操作失败"});// 在 async 函数中使用
async function example() {try {await Promise.reject("拒绝原因");} catch (error) {console.log(error); // 输出: "拒绝原因"}
}
example();

Promise.all()

等待所有 Promise 完成,或第一个 Promise 被拒绝。

// 所有 Promise 都成功
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);Promise.all([promise1, promise2, promise3]).then(values => {console.log(values); // 输出: [1, 2, 3]});// 其中一个 Promise 失败
const successPromise = Promise.resolve("成功");
const failurePromise = Promise.reject(new Error("失败"));Promise.all([successPromise, failurePromise]).then(values => {console.log(values); // 不会执行}).catch(error => {console.error(error.message); // 输出: "失败"});// 实际应用:并行请求多个 API
const fetchUser = Promise.resolve({ name: "张三" });
const fetchPosts = Promise.resolve([{ id: 1, title: "文章1" }]);
const fetchComments = Promise.resolve([{ id: 1, content: "评论1" }]);Promise.all([fetchUser, fetchPosts, fetchComments]).then(([user, posts, comments]) => {console.log("用户:", user);console.log("文章:", posts);console.log("评论:", comments);});

Promise.allSettled()

等待所有 Promise 完成(无论成功或失败)

const resolvedPromise = Promise.resolve("成功");
const rejectedPromise = Promise.reject("失败");Promise.allSettled([resolvedPromise, rejectedPromise]).then(results => {results.forEach((result, index) => {if (result.status === "fulfilled") {console.log(`Promise ${index}:`, result.value);} else {console.log(`Promise ${index}:`, result.reason);}});// 输出:// Promise 0: 成功// Promise 1: 失败});

Promise.race()

返回第一个完成(成功或失败)的 Promise

// 第一个 Promise 先完成
const fastPromise = new Promise(resolve => {setTimeout(() => resolve("快的"), 100);
});const slowPromise = new Promise(resolve => {setTimeout(() => resolve("慢的"), 500);
});Promise.race([fastPromise, slowPromise]).then(result => {console.log(result); // 输出: "快的"});// 超时控制
function timeout(ms) {return new Promise((_, reject) => {setTimeout(() => reject(new Error("超时")), ms);});
}function fetchWithTimeout(url, timeoutMs) {return Promise.race([fetch(url),timeout(timeoutMs)]);
}// 模拟使用
const mockFetch = Promise.resolve("数据获取成功");
fetchWithTimeout(mockFetch, 2000).then(data => console.log(data)).catch(error => console.error(error.message));

Promise.any()

返回第一个成功的 Promise,如果所有 Promise 都失败则抛出 AggregateError

// 第一个成功的 Promise
const failure1 = Promise.reject("错误1");
const failure2 = Promise.reject("错误2");
const success = Promise.resolve("成功");Promise.any([failure1, failure2, success]).then(result => {console.log(result); // 输出: "成功"});// 所有 Promise 都失败
const allFailures = [Promise.reject("错误A"),Promise.reject("错误B"),Promise.reject("错误C")
];Promise.any(allFailures).catch(error => {console.log(error instanceof AggregateError); // trueconsole.log(error.errors); // ["错误A", "错误B", "错误C"]});

Promise.try() (非标准,但常用)

立即执行异步函数,同步错误也会被捕获

// 模拟实现(非原生方法)
Promise.try = function(fn) {return new Promise(resolve => resolve(fn()));
};// 使用示例
function asyncOperation() {// 可能抛出同步错误if (Math.random() > 0.5) {throw new Error("同步错误");}return "操作成功";
}// 传统方式需要 try-catch
try {asyncOperation().then(console.log);
} catch (error) {console.error("捕获错误:", error.message);
}// 使用 Promise.try
Promise.try(asyncOperation).then(result => console.log(result)).catch(error => console.error("捕获错误:", error.message));
http://www.dtcms.com/a/598369.html

相关文章:

  • 直播网站建设费用腾讯云域名控制台
  • 山东兴润建设集团网站ps设计网站步骤
  • 广州网站 制作信科便宜seo就业
  • 基于ENAS与YOLOv8的草莓成熟度自动检测系统:原理、实现与性能优化(含详细代码)
  • 内网横向靶场——记录一次横向渗透(三)
  • 兰州电商平台网站建设设备外观设计效果图
  • 【XR开发系列】Unity下载与安装详细教程(UnityHub、Unity)
  • 深度学习——参数优化
  • 网站排名优化外包公司有限公司怎么纳税
  • Simulink 基础模块使用
  • 叫人做网站多少钱怎么根据视频链接找到网址
  • [论文阅读] 生成式人工智能嵌入对公众职业安全感冲击的影响机理及防范对策
  • 双桥区网站制作页面升访请广大狼
  • 余弦退火策略
  • Linux 网络:邻居子系统
  • 招聘网站开发成本揭阳网站设计公司
  • 网站建设三网合一指的是什么意思军队营房基础建设网站
  • Python教学基础:用Python和openpyxl结合Word模板域写入数据-由Deepseek产生
  • 保姆级CHARLS数据库使用教程
  • 光辉网站建设公司河南郑州建设网站
  • 如何使用 Gitblit 内置的 GitLFS 存储大文件
  • 网站开发公司 商业计划书信息流投放平台
  • [论文阅读] 软件工程 | 解决Java项目痛点:DepUpdater如何平衡依赖升级的“快”与“稳”
  • 建设一个网站需要多少钱青岛做网站eoe
  • 在数据“可用不可见”中寻找支付安全与体验的平衡
  • 男人女人做那个网站wordpress中文翻译插件
  • 东莞长安营销型网站建设宁夏百度公司
  • 网站开发课程论文北京最近发布会直播
  • 网站页面设计效果图设计专业招聘信息
  • 没有网站可以做百度排名吗1688网站建设与维护