AJAX 学习笔记

一、AJAX

1.1 特点

1.1.1 优点

  • 可以无需刷新页面与服务器端进行通信

  • 允许你根据用户时间来更新部分页面内容

1.1.2 缺点

  • 没有浏览历史,不能回退

  • 存在跨域问题(同源)

  • SEO 不友好

1.2 HTTP 超文本传输协议

1.2.1 请求报文

  • 请求方式(POST) / URL / 版本(HTTP/1.1)

  • Host: atguigu.com

    Cookie: name=zehui

    Content-type: application/x-www-form-urlencoded

    User-Agent: chrome 83

  • 空行

  • 请求体

1.2.2 响应报文

  • HTTP/1.1 200 OK

  • Content-type: text/html;charset=utf-8

    Content-length: 2048

    Content-encoding: gzip

  • 空行

  • 响应体

1.3 express的使用

npm init --yes
​
npm i express
// 引入express
const { response } = require('express')
const express = require('express')
    // 创建应用对象
const app = express()
    // 创建路由规划
app.get('/', (request, response) => {
        response.send('hello express')
    })
    // 监听端口启动服务
app.listen(8000, () => {
    console.log('服务已启动,8000端口监听中...');
})

127.0.0.1:8000查看请求

1.4 ajax 的基本操作

1.4.1 GET

const btn = document.querySelector('button')
const result_box = document.querySelector('.result__box')
btn.onclick = () => {
    // 创建对象
    const xhr = new XMLHttpRequest()
    // 初始化 设置请求方法和url
    xhr.open('GET', 'http://127.0.0.1:8000/server')
    // 发送
    xhr.send()
    // 事件绑定 处理服务端返回的结果
    // readyState 是xhr对象的属性 状态值: 0 1 2 3 4
    xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) { // 服务端返回了所有结果
            // 判断状态码
            if (xhr.status >= 200 && xhr.status < 300) {
                result_box.innerHTML = xhr.response
            } else {
                console.log('error');
            }
        }
    }
​
}
app.get('/server', (request, response) => {
    // 允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.send('hello ajax')
})

1.4.2 POST

const result_box = document.querySelector('.result__box')
result_box.addEventListener('mouseover', function() {
    const xhr = new XMLHttpRequest()
    xhr.open('POST', 'http://127.0.0.1:8000/server')
    // 设置请求头信息
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    xhr.setRequestHeader('name', 'szh')
    // 设置post方式的请求体
    xhr.send('a=1&b=2')
    xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                result_box.innerHTML = xhr.response
            }
        }
    }
})
const express = require('express')
const app = express()
app.post('/server', (req, res) => {
    // 设置响应头
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader('Access-Control-Allow-Header', '*')
    res.send('it is post')
})
app.listen(8000, () => {
    console.log('123');
})

1.4.3 服务端响应JSON数据

const box = document.querySelector('.box')
window.addEventListener('keypress', () => {
    const xhr = new XMLHttpRequest()
    xhr.responseType = 'json' // 设置响应体类型
    xhr.open('POST', 'http://127.0.0.1:8000/json-server')
    xhr.send()
    xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                box.innerHTML += xhr.response.name
            }
        }
    }
})
app.all('/json-server', (req, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader('Access-Control-Allow-Header', '*')
    const obj = {
        name: 'szh',
        age: '22'
    }
    res.send(obj)
})

1.5 nodemon 自动重启工具安装

nodemon - npm

1.6 IE浏览器缓存问题

解决方法:在请求后面加上一个时间戳

xhr.open('http://127.0.0.1:8000/ie?t=' + Date.now())

1.7 超时请求与异常

客户端发送请求

window.addEventListener('keypress', () => {
    const xhr = new XMLHttpRequest()
​
    /***********************************************/
    xhr.timeout = 2000 // 超时设置
    xhr.ontimeout = () => {
        // 超时回调
        console.log('请求超时或失败,重新发送请求...')
    }
    xhr.onerror = () => {
        // 网络异常回调
        console.log('网络异常,请检查网络后重新发送请求!')
    }
​
    xhr.open('POST', 'http://127.0.0.1:8000/timeout')
    xhr.send()
    xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                result_box.innerHTML = xhr.response
            }
        }
    }
})

服务端设置延时模拟超时、浏览器设置offline模拟断网状态

// 请求超时与异常
// 延时响应
app.post('/timeout', (req, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*')
    setTimeout(() => {
        res.send('请求时间为3s')
    }, 3000)
})

1.8 取消请求(手动)

 xhr.abort() //取消发送

1.9 请求发送重复问题

思路:添加一个全局变量进行判断发送的状态,false时才进行发送。

const submit = document.querySelector('.submit')
let xhr = null
let isSending = null // 判断是否在发送请求
submit.addEventListener('click', () => {
    if (!isSending) {
        xhr = new XMLHttpRequest()
        isSending = true
        xhr.open('GET', 'http://127.0.0.1:8000/repeat')
        xhr.send()
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                isSending = false
            }
        }
    } else {
        console.log('请求正在发送中...');
    }
})

二、JQuery中的Ajax

.get() ​.post() .ajax()

btn[0].onclick = function() {
    /*
         ** 三个参数 url 携带参数 回调函数(响应体)
         */
    let jqxhr = $.get('http://127.0.0.1:7000/getAjax', {
        a: 1,
        b: 2
    }, function(res) {
        console.log(res);
    }).done(() => {
        console.log('success')
    }).always(() => {
        console.log('complete')
    })
    }
btn[1].onclick = function() {
    let jqxhr = $.post('http://127.0.0.1:7000/postAjax', {
        a: 1,
        b: 2
    }, function(res) {
        console.log(res);
    }).done(() => {
        console.log('success')
    }).always(() => {
        console.log('complete')
    })
    }
btn[2].onclick = function() {
    $.ajax({
        type: 'POST',
        url: 'http://127.0.0.1:7000/postAjax',
        data: {
            k: 1,
        },
        dataType: 'json',
        success: data => {
            console.log(data)
        },
        headers: {
            t: 123
        },
    })
}
/*
 ** JQuery-Ajax
 */
app.get('/getAjax', (req, res) => {
    res.setHeaders('Access-Control-Allow-Origin', '*')
    res.send('jquery-get')
})
app.all('/postAjax', (req, res) => {
    res.setHeaders('Access-Control-Allow-Origin', '*')
    res.setHeaders('Access-Control-Allow-Headerss', '*')
    const obj = {
        name: 'szh'
    }
    res.send(JSON.stringify(obj))
})

fetch()

fetch 规范与 jQuery.ajax() 主要有以下的不同:

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject,即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve(如果响应的 HTTP 状态码不在 200 - 299 的范围内,则设置 resolve 返回值的 ok 属性为 false),仅当网络故障时或请求被阻止时,才会标记为 reject。

  • fetch 不会发送跨域 cookie,除非你使用了 credentials初始化选项

基本语法

// fetch请求
async function fetchData(url = '', data = {}) {
    const response = await fetch(url, {
        method: 'POST',
        mode: "cors",
        cache: "no-cache",
        credentials: "same-origin",
        headers: {
            'Content-Type': 'application/json',
            szh: 123
        },
        redirect: "follow",
        referrerPolicy: "no-referrer",
        body: JSON.stringify(data)
    })
    return response.json()
}
window.addEventListener('keypress', () => {
    fetchData('http://127.0.0.1:7000/fetch', {
        name: 'szh'
    }).then(data => {
        console.log(data.ok)
        console.log(data)
    }).catch(e => {
        console.log(e)
    })
})
// fetch
app.all('/fetch', (req, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader('Access-Control-Allow-Headers', '*')
    const obj = {
        name: 'szh'
    }
    res.send(JSON.stringify(obj))
})

三、跨域问题

3.1 同源策略

同源策略是浏览器的一种安全策略,所谓的同源指:协议域名端口号 必须完全相同

违背同源策略即为跨域

3.2 解决跨域问题

3.2.1 JSONP

  1. 是什么?

    JSONP (JSON with Padding),是一个非官方的跨域解决方案, 只支持get请求

  2. 怎么工作的?

    网页有一些标签具有跨域能力,比如:img、link、iframe、script

    JSONP 就是利用script标签的跨域能力来发送请求的。

  3. 如何使用?

    function handle(obj) {
        console.log(obj);
        if (obj.exit === 1) {
            $('input')[0].style.color = 'red'
        }
    }
    ​
    $('input').blur(() => {
        let uname = $(this).val
        // 1-动态创建script标签
        const script = document.createElement('script')
        // 2-设置src
        script.src = 'http://127.0.0.1:7000/jsonp'
        // 3-添加节点
        document.body.appendChild(script)
    })
    // 跨域问题
    app.all('/jsonp', (req, res) => {
        const data = {
            exit: 1,
            msg: '账号已存在'
        }
        let obj = JSON.stringify(data)
        res.end(`handle(${obj})`)
    })

3.2.2 CORS

  1. 是什么?

    CORS (Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和 post 请求。跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源

    跨源资源共享(CORS) - HTTP | MDN

  2. 怎么工作的?

    CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。

  3. 如何使用?

    res.setHeader('Access-Control-Allow-Headers', '*')
    // 第二个参数是允许跨域的请求

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值