XMLHttpRequest和Promis

本文探讨了XMLHttpRequest在原生JS中的使用,包括Ajax的基本操作和回调函数的概念。接着,文章介绍了Promise作为ES6提出的异步代码优化方案,详细阐述了Promise的经典格式、状态变化以及如何使用then和catch处理异步操作。通过Promise,可以有效地避免回调地狱,提高代码可读性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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(值)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值