# 1. 前端网络请求都有哪些方式?webSocket 是什么?

这道题目主要考察对前端网络请求知识点的掌握,能够对各种请求的优缺点能够了如指掌掌握,并能够对开源库 axios 的原理了如指掌。

前端中提供的原生网络请求有如下几种:

  • XMLHTTPRequest Leval1

IE5 首次提出了 XMLHTTPRequest, 它实现了 ajax(Asynchronous JavaScript XML),可以在不刷新页面的情况下更新 web 页面中的内容,也就是一种局部更新策略。XMLHTTPRequest 的出现让 ajax 这种技术走向了成熟。

// 同步请求
function requestSyncWithXHR1() {
    let xhr = new XMLHttpRequest();
    // 准备发起请求
    xhr.open('get', '/api/user', false);
    // 立即发起请求
    xhr.send(null);
    // 获取 xhr 的状态码
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
        alert(xhr.responseText);
    }
    else {
        alert('request error: ' + xhr.status);
    }
}
// 异步请求
function requestAsyncWithXHR1() {
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = e => {
        if (xhr.readyState === 4) {
            // 获取 xhr 的状态码
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
                alert(xhr.responseText);
            }
            else {
                alert('request error: ' + xhr.status);
            }
        }
    };
    // 异步请求
    xhr.open('get', '/api/user', true);
    xhr.send(null);
}
  • XMLHTTPRequest Leval2

XMLHTTPRequest 成为了 W3C 标准,所有浏览器都支持该特性,同时对 Leval1 进行了扩展,支持了:

a、支持了 FormData,更容易地序列号表单数据;

b、添加了 onload 事件,监听网络请求完成;

c、添加了 onprogress 事件,可见听数据接收的进度;

d、添加了 timeout 机制

function requestAsyncWithXHR2() {
    let xhr = new XMLHttpRequest();
    // 设置超时时间
    xhr.timeout = 5000;
    // 设置 HTTP Header
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onload = function(e) {
        // 获取 xhr 的状态码
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
            alert(xhr.responseText);
        }
        else {
            alert('request error: ' + xhr.status);
        }
    };
    // 监听进度,比如监听文件上传进度
    xhr.onprogress = function(e) {

    };
    xhr.open('post', '/user/add', true);
    // post 请求的 body
    let formData = new FormData();
    formData.set('name', 'suyan');
    formData.set('pwd', '123suyan');
    xhr.send(formData);
}
  • Fetch API

这是一种更现代的 API,具有以下特点:

  • 可以应用与工作线程,比如 web worker,而 XMLHTTPRequest 只能在主线程执行;
  • 使用起来更简单,更现代;
  • 返回为 Promise;
  • 只支持异步,而 XMLHTTPRequest 可支持同步和异步
  • 兼容性不好,IE浏览器压根不能用
  • 提供了 Request、Response、Header 对象,使用起来更友好
  • 读取 body 有多种方式 text、formdata、arrayBuffer、blob
function requestWithFetch() {
    const header = new Headers({
        'Content-Type': 'application/x-www-form-urlencoded'
    });
    fetch('/add/user', {
        method: 'POST',
        body: JSON.stringify({
            name: 'suyan'
        }),
        headers: header
    }).then(res => {
        if ((res.status >= 200 && res.status < 300) || res.status === 304) {
            alert('success!')
        }
        else {
            alert('error: ' + res.status);
        }
    })
}
  • Beacon API

Beacon,汉语意思信标,这种与前面几种都不一样,它是为了满足离开页面时可以发起的一种请求。比如统计网页使用情况,通常在 unload 中发送网络请求,但是发送异步请求时,一旦页面退出,网络请求就会被取消,如果发送同步请求,影响用户体验,而 Beacon API 可以保证及时页面关闭,浏览器仍然会发起请求。

特点:

  • 可以在任意地方使用;
  • 页面即使关闭,也会发起请求;
  • 发起请求无法干预,也不能监听其结果;
  • 发起请求会带有 cookie 信息;
function beaconApi() {
    navigator.sendBeacon('https://lefex.gitee.io/', '{name: "suyan"}');
}
  • websocket

它是一种长连接,客户端和服务端直接都可以发送和接收消息。

function websocket() {
    let socket = new WebSocket("ws://lefex.gitee.io/server.php");
    socket.onopen = function() {
        // socket open
    };
    socket.onerror = function() {
        // socket error
    };
    socket.onclose = function() {
        // socker close
    };
    let stringData = "suyan nihao";
    // 发送消息
    socket.send(stringData);
    let buffer = Uint8Array.from([1, 2, 3]);
    socket.send(buffer);
    // 接收到消息
    socket.onmessage = function(e) {
        let data = e.data;
    }
}

# 相似问题:

  • ajax axios fetch的区别
  • 原生 ajax 原理,如何缓存。
  • 如何用promise封装一个ajax
  • 用原生xhr发送一个请求