使用AJAX、Axios、Fetch


AJAX

  • AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML)
  • AJAX最主要的两个特性:在不重新加载页面的情况下发送请求给服务器;受并使用从服务器发来的数据

    AJAX请求的五个步骤

    • 1.建立XMLHttpRequest对象
    • 2.设置回调函数
    • 3.配置请求信息,(如open,get方法),使用open方法与服务器建立链接
    • 4.向服务器发送数据
    • 5.在回调函数中针对不同的响应状态进行处理

readyState

  • 0 -(请求未初始化)还没有调用send()方法
  • 1 -(正在加载)已调用send()方法,正在发送请求
  • 2 -(加载成功)send()方法执行完成,已经接收到全部响应内容
  • 3 -(交互)正在解析响应内容
  • 4 -(完成)响应内容解析完成,可以在客户端调用了

使用

function ajax(url, method="GET", data=null, async=true) {
    // 声明XMLHttpRequest 
    // 在IE5和IE6中需要使用ActiveX对象 let XRH = new ActiveXObject("Microsoft.XMLHTTP");
    let XHR = XMLHttpRequest;

    // 创建XMLHttqRequest
    XHR = new XMLHttpRequest()

    // 初始化请求参数
    XHR.open(method, url, async)

    // 设置响应的数据类型
    XHR.responseType = 'json'

    // 设置请求头(求头的设置必须在xhr open之后,并且在send之前)
    XHR.setRequestHeader("Content-type", "text/html"); // applicationx-www-form-urlencoded  text/html  application/json multipart/form-data

    // 设置请求状态改变时执行的函数
    XHR.onreadystatechange = function() {
      if (XHR.readyState === 4 ) return
      console.log(`响应状态:${XHR.status}`,"FINISH") 
      if(XHR.status == 200) {
        // 获取服务器响应的数据,XHR.responseText为响应体
        var res = XHR.responseText
        console.log(res)
        // 解析数据(数据为JSON数据时)
        // res = JSON.parse(res)
      }
    }

    // 异常处理
    XHR.onerror = function() {
      console.log('Network request failed')
    }

    // 发起请求
    XHR.send(data)
  }
// 调用(百度首页的调试窗口中调用)
ajax("https://www.baidu.com");
ajax("https://www.baidu.com","POST","A=1&B=2");

参考

Fetch

  • Fetch是浏览器内置API,在浏览器环境中,可以通过顶层对象window获取
  • fetch()是XMLHttpRequest(ajax使用的就是XMLHttpRequest)的升级版,用于在JavaScript脚本里面发出HTTP请求

语法

let promise = fetch(url, [options])
// 完整options对象
/**
  {
    method: "GET", // HTTP 请求的方法,POST、DELETE、PUT等
    headers: { // 请求头
      "Content-Type": "text/plain;charset=UTF-8"
    },
    body: undefined, // POST 请求体
    referrer: "about:client",
    referrerPolicy: "no-referrer-when-downgrade", // 指定了 HTTP 头部 referer 字段的值
    mode: "cors", // 请求的模式
    credentials: "same-origin",
    cache: "default", // 请求的 cache 模式
    redirect: "follow", // 可用的 redirect 模式
    integrity: "",
    keepalive: false,
    signal: undefined
  }
*/

GET请求

fetch(URL)
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(err => console.log('Request Failed', err)); 

使用await语法

async function fetchText() {
  let response = await fetch(URL);
  console.log(response.status); 
  console.log(response.statusText);
}

POST请求

const response = await fetch(URL, {
  method: 'POST',
  headers: {
    "Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
  },
  body: 'foo=bar&lorem=ipsum',
});

const json = await response.json();

POST提交JSON数据

const user =  { name:  'John', surname:  'Smith'  };
const response = await fetch(URL, {
  method: 'POST',
  headers: {
   'Content-Type': 'application/json;charset=utf-8'
  }, 
  body: JSON.stringify(user) 
});

POST提交表单数据

const form = document.querySelector('form');

const response = await fetch(URL, {
  method: 'POST',
  body: new FormData(form)
})

文件上传

const input = document.querySelector('input[type="file"]');

const data = new FormData();
data.append('file', input.files[0]);
data.append('user', 'foo');

fetch(URL, {
  method: 'POST',
  body: data
});

上传二进制数据

let blob = await new Promise(resolve =>   
  canvasElem.toBlob(resolve,  'image/png')
);

let response = await fetch(URL, {
  method:  'POST',
  body: blob
});

取消fetch()请求

  • fetch()请求发送以后,如果中途想要取消,需要使用AbortController对象
    let controller = new AbortController();
    let signal = controller.signal;
    
    fetch(url, {
      signal: controller.signal
    });
    
    signal.addEventListener('abort',
      () => console.log('abort!')
    );
    
    controller.abort(); // 取消
    
    console.log(signal.aborted); // true

Axios

GET请求

// get请求携带参数
axios.get('/user?ID=5422')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// 也可以这样写
axios.get('/user', {
    params: {
      ID: 5422
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
// 相应类型为流文件
axios({
  method: 'get',
  url: 'http://www.xxx.com/test',
  responseType: 'stream'
})
  .then(function(response) {
  response.data.pipe(fs.createWriteStream('xxx.jpg'))
});

POST请求

axios.post('/user', {
    firstName: '三',
    lastName: '张'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// 也可以配置参数
axios({
  method: 'post',
  url: '/user/001',
  data: {
    firstName: '三',
    lastName: '张'
  }
});

并行请求

function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // Both requests are now complete
  }));

创建实例

let instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'custom header content'}
});

Response

axios.get('/user/12345')
  .then(function(response) {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
  });

Config

// 全局默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

// Custom instance defaults

// Set config defaults when creating the instance
var instance = axios.create({
  baseURL: 'https://api.example.com'
});

// Alter defaults after instance has been created
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;

// Config order of precedence

// Create an instance using the config defaults provided by the library
// At this point the timeout config value is `0` as is the default for the library
var instance = axios.create();

// Override timeout default for the library
// Now all requests will wait 2.5 seconds before timing out
instance.defaults.timeout = 2500;

// Override timeout for this request as it's known to take a long time
instance.get('/longRequest', {
  timeout: 5000
});

拦截器

// Intercept request/responses

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });
  
// Remove interceptor

var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

// Custom instance interceptors

var instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});

错误处理

// Catch error

axios.get('/user/12345')
  .catch(function (error) {
    if (error.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
    } else if (error.request) {
      // The request was made but no response was received
      // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
      // http.ClientRequest in node.js
      console.log(error.request);
    } else {
      // Something happened in setting up the request that triggered an Error
      console.log('Error', error.message);
    }
    console.log(error.config);
  });

// Custom HTTP status code error

axios.get('/user/12345', {
  validateStatus: function (status) {
    return status < 500; // Reject only if the status code is greater than or equal to 500
  }
})

取消请求

// Cancel request with cancel token

var CancelToken = axios.CancelToken;
var source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // handle error
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');

// Create cancel token

var CancelToken = axios.CancelToken;
var cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // An executor function receives a cancel function as a parameter
    cancel = c;
  })
});

// cancel the request
cancel();

  目录