JavaScript全解析——Ajax(下)

Ajax(下)

●http 传输协议

○http(s) 协议规定了, 只能由前端主动发起
○并且在传输的过程中, 只能传递 字符串

●http 协议过程

1.建立连接

浏览器和服务器进行连接建立
基于 TCP/IP 协议的三次握手

2.发送请求

要求前端必须以 请求报文 的形式发送

报文由浏览器组装, 我们只需要提供对应的信息即可

报文包含的内容

请求报文行
请求方式, 请求地址, 传输协议
请求报文头(对本次请求的一些说明信息)
userAgent: 请求方终端信息
accept: 期望后端返回的数据类型
content-type: 请求携带的 "材料" 的数据格式
  cookie: 只要 cookie 空间内有内容, 会自动携带
  请求报文空行
  请求报文体(不是所有请求都有)

3.接收响应

要求后端必须以响应报文的形式返回
报文由服务器组装
响应报文包含的内容
响应报文行
响应状态码, 简单信息描述响应状态码, 传输协议
响应报文头(对本次响应的一些说明信息)
server: 哪一个服务器给你返回的信息
date: 时间, 服务器时间
content-length: 响应体长度
content-type: 响应数据类型
响应报文体(后端返回给前端的一些信息)

4.断开连接

浏览器和服务器断开连接
基于 TCP/IP 协议的四次挥手
●响应状态码
○100199 表示连接继续
○200299 表示各种成功
○300399 表示重定向
○400499 表示各种客户端错误
○500~599 表示各种服务端错误
●回调函数
○把函数 A 以实参的形式传递到 函数 B 内
○在函数 B 内以形参的方式调用到 函数 A
○此时我们可以把函数 A 叫做函数 B 的 回调函数
○我们在封装异步代码的时候会用到回调函数

function fnA () {console.log('我是 fnA 函数内部的代码')}

function fnB(callback) {callback()}

fnB(fnA)

●使用回调函数封装一个异步代码

function fn(jinnang = () => {}) {
    console.log("班长去买水了");
    const timer = Math.ceil(Math.random() * 3000);
    setTimeout(() => {
        console.log("班长买完水了");
        console.log("耗时", timer);
        console.log("按照锦囊内的内容行事");
        jinnang();
    }, timer);
}
/**
 * fn 函数一旦调用, 班长出发开始去买水
 *      在班长出发的时候, 给他一个锦囊
 */
fn(() => {
    console.log("去买一瓶牛奶");
});
fn();

●上述代码已经完成了一个异步的封装
●不过在工作中我们更多的是封装网络请求这种异步代码
●但是我们这里通过一个 '买水耗时' 来模拟一个网络请求的延迟, 我们约定如果时间超过 3500 毫秒, 那么就算是失败, 否则就是成功

function fn(jinnang = () => {}) {
    console.log("班长去买水了");
    const timer = Math.ceil(Math.random() * 3000) + 2000;
    setTimeout(() => {
        if (timer > 3500) {
            console.log("请求失败", timer);
        } else {
            console.log("请求成功", timer);
        }
    }, timer);
}
/**
 * fn 函数一旦调用, 班长出发开始去买水
 *      在班长出发的时候, 给他一个锦囊
 */
fn(() => {
    console.log("去买一瓶牛奶");
});
fn();

●此时我们已经封装完毕了, 只不过这种封装方式会带来另一个问题, 就是回调地狱
●回调地狱: 当你使用回调函数过多的时候, 会出现的一种代码书写结构
●需求:
○再买水成功后, 让班长帮忙退掉
○在推掉以后, 再次让班长帮忙买水 (此时必须要在前一瓶水购买完成之后再去购买)
○在第二次买水成功以后, 再次让班长去买水

fn(
    () => {
        console.log("班长第一次买水成功, 帮我退掉");
        fn(
            () => {
                console.log("班长第二次买水成功");
                fn(
                    () => {
                        console.log("班长第三次买水成功");
                    },
                    () => {
                        console.log("班长第三次买水失败");
                    }
                );
            },
            () => {
                console.log("班长第二次买水失败");
            }
        );
    },
    () => {
        console.log("班长第一次买水失败");
    }
);

●这段代码运行没有任何问题, 但是阅读起来极其不利于理解
○原因:
■按照回调函数的语法进行封装, 只能通过传递一个函数作为参数来调用
■当你使用回调函数过多的时候, 会出现回调地狱的代码结构
○解决:
■不按照回调函数的语法封装
■ES6 推出了一种新的封装异步代码的方式, 叫做 Promise (承诺, 期约)

Promise

是一种异步代码的封装方案
因为换了一种封装方案, 不需要安装回调函数的方式去调用, 需要按照 promise 的形式去调用
注意 promise 不是解决 异步问题的, 而是解决回调地狱问题的

●认识 Promise

○promise 的三种状态
■持续: pending
■成功: fulfilled
■失败: rejected

○promise 的两种转换
■从持续转为成功
■从持续转为失败

○promise 的基础语法
■ES6 内置构造函数

○promise 的语法
■const p = new Promise(function () {})

○promise 对象可以触发的两个方法
■p.then(函数); 成功时执行
■p.catch(函数); 失败时执行
●promise 封装一个异步函数

const p = new Promise(function (resolve, reject) {
    // resolve: 是一个形参, 名字自定义, 值是一个函数, 当你调用的时候, 会把当前 promise 的状态转换为 成功
    // reject: 是一个形参, 名字自定义, 值是一个函数, 当你调用的时候, 会把当前 promise 的状态转换为 失败
    // resolve 和 reject 调用时可以传递一个参数, 这个参数会被传递给对应的 then catch
    const timer = Math.ceil(Math.random() * 3000) + 2000;
    setTimeout(() => {
        if (timer > 3500) {
            console.log("买水失败, 耗时 ", timer);
            reject("奖励一个bug");
        } else {
            console.log("买水成功, 耗时: ", timer);
            resolve("送你十个bug");
        }
    }, timer);
});

p.then(function (address) {
    console.log("班长买水成功咯~~~", address);
});
p.catch(function (address) {
    console.log("班长买水失败咯~~~", address);
});

● 封装 promise 为函数

function fn() {
    const p = new Promise(function (resolve, reject) {
        const timer = Math.ceil(Math.random() * 3000) + 2000;
        setTimeout(() => {
            if (timer > 3500) {
                reject("班长买水失败");
            } else {
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值