axios的一般使用

1,010 阅读3分钟

概述

何为axios? 个人理解为【Ajax IO Stream】

一款棒棒的、使用广泛的、基于Promise的、具有请求拦截功能的、具有请求撤销功能的、方便做关联并发的、配置丰富的ajax库;

axios中文文档

安装依赖

npm i axios

注意事项

注意请求成功时,res.data才是真正从服务端返回的数据,其余信息为axios框架自行封装的一些信息

发起GET请求

axios
.get(
  "https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/goods/list/1"
)
.then(function (res) {
  console.log("res=", res);
})
.catch(function (err) {
  console.log("err=", err);
});

发起POST请求

携带JSON数据

axios
.post(
"https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/login",
  {
    username: "admin",
    password: "123456",
  }
)
.then(function (res) {
  console.log("res=", res);
  response.value = res.data;
  error.value = "暂无数据";
})
.catch(function (err) {
  console.log("err=", err);
  error.value = err;
  response.value = "暂无数据";
});

携带表单数据

const params = new URLSearchParams();
params.append("username", "admin");
params.append("password", "123456");

axios
  .post(
    "https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/login",
    params
  )
  .then(function (res) {
    console.log("res=", res);
  })
  .catch(function (err) {
    console.log("err=", err);
  });

玩一下async/await

const postForm = async () => {
  try {
    const params = new URLSearchParams();
    params.append("username", "admin");
    params.append("password", "123456");
    
    const { data } = await axios.post("http://httpbin.org/post", params);
    response.value = data;
    error.value = "暂无数据";
  } catch (err) {
    error.value = err;
    response.value = "暂无数据";
  }
};

合并多个并发请求的数据

function getOdd() {
    return axios.get(
      "https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/goods/list/1"
    );
}

function getEven() {
    return axios.get(
      "https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/goods/list/2"
    );
}

axios
.all([getOdd(), getEven()])
.then(
  axios.spread(function ({ data: odd }, { data: even }) {
    // 两个请求现在都执行完成
    console.log("odd", odd);
    console.log("even", even);

    response.value = odd.data.concat(even.data);
    error.value = "暂无数据";
    console.log(response.value.length);
  })
)
.catch((err) => {
  console.log("err=", err);
  error.value = err;
  response.value = "暂无数据";
});

配置不同的axios实例(用于请求不同的业务)

const instance = axios.create({
    baseURL: "http://httpbin.org",
    timeout: 3000,
    headers: { "X-Custom-Header": "foobar" },
});

/* 发起请求 */
instance
.post("/post", {
  username: "admin",
  password: "123456",
})
.then((data) => (response.value = data))
.catch((err) => (error.value = err));

配置拦截器

拦截器可以统一对所有请求和响应做预处理

// 添加请求拦截器
instance.interceptors.request.use(
    function (config) {
      // 在发送请求之前做些什么:为所有请求配置请求头authorization 令其携带身份认证token
      config.headers["authorization"] = "Bearer mytoken";
      return config;
    },
    function (error) {
      // 对请求错误做些什么
      return Promise.reject(error);
    }
);

// 添加响应拦截器
instance.interceptors.response.use(
    function (response) {
      // 对响应数据做点什么:从响应中剥离出【服务器端返回的数据】 过滤掉axios自行封装的信息
      return response.data;
    },
    function (error) {
      // 对响应错误做点什么
      return Promise.reject(error);
    }
);

axios请求的取消

一个CancelToken可以取消多个请求:

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

axios
  .get("/user/12345", {
    cancelToken: source.token,
  })
  .catch(function (thrown) {
    if (axios.isCancel(thrown)) {
      console.log("Request canceled", thrown.message);
    } else {
      // 处理错误
    }
  });

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

// 必要时取消请求(message 参数是可选的) 
// 例如离开当前页面前取消未完成的请求
source.cancel("Operation canceled by the user.");

经典的三层封装

第一层/实例层:配置请求实例与拦截器,导出请求实例

const instance = axios.create({

  // baseURL: "http://localhost:9000/api",

  baseURL: '/api',

  timeout: 3000

})



// 添加请求拦截器

instance.interceptors.request.use(

  function(config) {

    // 在发送请求之前做些什么

    config.headers['Authorization'] = `Bearer ${getToken()}`

    return config

  },

  function(error) {

    // 对请求错误做些什么

    return Promise.reject(error)

  }

)



// 添加响应拦截器

instance.interceptors.response.use(

  function(response) {

    // 对响应数据做点什么

    return response.data

  },

  function(error) {

    // 对响应错误做点什么

    return Promise.reject(error)

  }

)

第二层/操作层:封装并导出通用增删改查方法

export async function doPost(url, data, conf) {

  try {

    const ret = await instance.post(url, data, conf)

    return ret

  } catch (error) {

    handleErr(`doPost@${url}`, error)

  }

}



export function doDelete(url,conf) {

  return instance.delete(url, conf)

}



export function doPut(url, data, conf) {

  return instance.put(url, data, conf)

}



export async function doGet(url, conf) {

  try {

    const ret = await instance.get(url, conf)

    return ret

  } catch (error) {

    handleErr(`doGet@${url}`, error)

  }

}

第三层/业务层:业务逻辑请求封装

import { doDelete, doGet, doPost, doPut } from "../network/request";

export async function addGoods(goods) {
    return await doPost("/goods/0", goods);
}

export async function deleteGoods(goods) {
    return await doDelete(`/goods/${goods._id}`);
}

export async function updateGoods(goods) {
    console.log("updateGoods", goods);
    let gid = goods._id;
    delete goods._id;
    return await doPut(`/goods/${gid}`, goods);
}

export async function getGoodsByPage(page) {
    const data = await doGet(`/goods/list/${page % 2 === 1 ? 1 : 2}`);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // return data;
            resolve(data);
        }, 2000);
    });
}

写在最后

如果喜欢,我们还可以给所有Vue/React组件来一个useAxios的小hook!

大致实现思路如下:

  • 让url作为入参,返回一组响应式数据{loading,data,error};
  • 组件一挂载就立即请求数据,此时loading为true;
  • 请求完毕后,data与error必是一实一空,loading为false;
  • 组件卸载时,如果loading为true,则自动取消未完成请求;