后端index.js注册网址并写入数据
var router=require("./router.js")
router.get("/news",function(req,res){
var obj={data:[{title:"新闻1",content:"内容1",id:1},
{title:"新闻2",content:"内容2",id:2},
{title:"新闻3",content:"内容3",id:3}
]}
var str=JSON.stringify(obj)
res.setHeader("content-Type","text/json;charset=utf8")
res.end(str)
})
router.get("/author",function(req,res){
var obj=[{name:"lily",id:1},
{name:"lucy",id:2},
{name:"jack",id:3}
]
var str=JSON.stringify(obj)
res.setHeader("content-Type","text/json;charset=utf8")
res.end(str)
})
前端index.html文件请求news的数据:
前端index.html文件请求author的数据:
请求 news 和 author 这两个网址接口的数据就要发送两次Ajax网络请求才能获得不同的数据,若想请求其他接口的数据就要写更多的网络请求代码。这样就很麻烦,因为每次请求的代码是一样的,只是请求的网址和请求到的数据的处理方式不同。所以,可以根据这个特点设计一个网络请求工具来简化代码,使网络请求更灵活。
tool(url,cb):
tool函数就是一个简单的封装了ajax网络请求的工具
tool函数先用ajax请求传入的第一个参数url对应网址
当请求到并返回数据时 就把数据传给cb函数使用(调用cb)去执行业务
此时能满足不同的网址请求和各样的业务,实现代码复用
当fn点击事件发生后,tool工具函数就会请求网址得到数据,再将数据传给业务(回调)函数,开始执行业务
前端index.html文件请求数据:(author.html同理)
工具文件 tool.js
function tool(url, cb) {
//封装Ajax网络请求代码
var xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")
xhr.open("GET", url, true)
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
//将请求到的数据传给cb回调函数执行业务
cb(xhr.responseText)
}
}
}
后端index.js注册网址并写入数据
var router=require("./router.js")
router.get("/news",function(req,res){
var obj={data:[{title:"新闻1",content:"内容1",id:1},
{title:"新闻2",content:"内容2",id:2},
{title:"新闻3",content:"内容3",id:3}
]}
var str=JSON.stringify(obj)
res.setHeader("content-Type","text/json;charset=utf8")
res.end(str)
})
router.get("/author",function(req,res){
var obj=[{name:"lily",id:1},
{name:"lucy",id:2},
{name:"jack",id:3}
]
var str=JSON.stringify(obj)
res.setHeader("content-Type","text/json;charset=utf8")
res.end(str)
})
请求结果:
用回调函数封装Ajax需要自己设计tool函数,而通过jquery只需要一个引入一个jquery框架就可以实现以上效果
修改以上代码:
1、弃用tool.js
2、将 替换为
3、将tool函数名 替换为 $.get
前端author.html文件请求数据:(index.html同理)
请求结果:
ajax请求回调地狱
promise封装ajax
promise语法:
(1) promise:
Promise是一个 构造函数, 用于创建Promise对象
Promise对象:可以理解为一个处理异步操作的容器
(2) promise对象的三个状态.:
- pending(进行中)
- fulfilled (已成功)
- rejected(已失败)
- 只有异步操作的结果可以决定当前是哪一种状态 任何其他操作都无法改变这个状态
(3) promise对象的状态改变:
- 从pending变为fulfilled 此时应该执行 resolve()
- 从pending变为rejected 此时应该执行 reject()
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果
- resolve() 和 reject() 只能执行一个
注:promise本质不是控制 异步代码的执行顺序,而是控制异步代码结果处理的顺序
(4) 使用:
1.实例化Promise对象 : 将异步操作放入Promise中
- resolve:异步操作 成功状态
- reject : 异步操作 失败状态
2.调用then() 方法: 处理异步操作结果
promise对象.then((data)=>{ 处理成功数据 },(err)=>{ 处理失败信息 })
promise静态方法:(常见于笔试题中)
- Promise.resolve():将现有对象转为 Promise 对象
var p1=Promise.resolve(200)//传入的数据 封装成产生正确数据的Promise对象 console.log(p1) //200 p1.then((data)=>console.log(data)) //等同于 var p1=new Promise((resolve,reject)=>{ resolve(200) }) p1.then((data)=>console.log(data))
- Promise.reject():返回一个新的 Promise 实例 该实例的状态为
rejected
var p3=Promise.reject(200) //传入的数据 封装成产生错误数据的Promise对象 console.log(p3) //200 p3.catch(e=>console.log(e)) //200
- Promise.all():用于将多个 Promise 实例,包装成一个新的 Promise 实例
var p1=new Promise((n1,n2)=>{ $.get("/ajax1",(data)=>{ n1(data) }) }) var p2=new Promise((n1,n2)=>{ $.get("/ajax2",(data)=>{ n1(data) }) }) var p3=new Promise((n1,n2)=>{ $.get("/ajax3",(data)=>{ n1(data) }) }) var p=Promise.all([p1,p2,p3]) p.then((arr)=>{ conosle.log(arr) }) /*只有当三个promise对象的状态都为fulfilled,p的状态才会变为fulfilled 此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数 */ /*只要有一个promise对象被rejected,p的状态就会变成rejected 此时第一个被rejected的实例的返回值会传递给p的回调函数 */
原理 :
在then方法中返回一个promise对象
- 链式嵌套,需在上一个promise对象的then方法中返回下一个promise对象进而实现连调
解决上述异步回调地狱(回调函数层次嵌套)的问题
function myaxios(url) {
return new Promise((resolve, reject) => {
//封装ajax
try {
//try里的代码3种情况: 语法错误|语法正确但产生错误的业务数据|正确的业务数据
let xhr = new XMLHttpRequest() || ActiveXObject("xxx")
xhr.open("GET", url, true)
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
console.log(123)
if (xhr.status == 200) {
resolve(xhr.responseText)
} else if (xhr.status == 404) {
reject(xhr.responseText)
} else {
reject("net err")
}
}
}
} catch (e) {
reject(xhr.responseText)
}
})
}
var p1 = myaxios('/ajax')
p1.then((data1) => {
console.log(data1)
return myaxios('/ajax1')
})
.then((data2) => {
console.log(data2)
return myaxios('/ajax2')
})
.then((data3) => {
console.log(data3)
return myaxios('/ajax3')
})
.then((data4) => {
console.log(data4)
})
.catch((e) => {
console.log(e)
})
var p1=axios('/ajax')
p1.then((data1)=>{
console.log(data1.data)
return axios('/ajax1')
})
.then((data2)=>{
console.log(data2.data)
return axios('/ajax2')
})
.then((data3)=>{
console.log(data3.data)
return axios('/ajax3')
})
.then((data4)=>{
console.log(data4.data)
})
.catch((e)=>{
console.log(e)
})
示例:
// 直接请求ajax1
var res=fetch("/ajax1")
//res是一个promise对象 这个对象内部有后端传过来的二进制包
res.then((data)=>{
return data.json() //调用函数解二进制包
})
.then((result)=>{
console.log(result)
})
写得很详细的一个博主的文章:
原文链接:https://blog.csdn.net/qq_43539854/article/details/125053587
async语法
(1)函数前面使用async修饰
(2)函数内部:promise操作使用await修饰 await代替then方法取数据
- await 后面是promise对象, 左侧的返回值就是这个promise对象的then方法中的结果
- await 只能取出正确的数据
- await 必须要写在async修饰的函数中,不能单独使用,否则程序会报错
- await 是遍历器的语法糖
终极高内聚低耦合
let data1=await new Promise((n1,n2)=>{n1(2000)})
console.log(data1) //打印2000
let data2=await axios('/ajax2')
console.log(data2)
let data3=await axios('/ajax3')
console.log(data3)
let data4=await axios('/ajax4')
console.log(data4)