Skip to content
导航栏

适配 Yao 的 amis fetcher

默认情况下,amis 会使用一个默认的 fetcher,这个 fetcher 会直接发起请求。 Amis 框架对返回数据格式有一定的要求。

为了让 amis 适配 yao 返回的数据格式,需要创建一个适配 yao 的 fetcher,主要负责请求数据和处理响应。

创建自定义的 fetcher

amis fetcher 的作用是发送请求和处理响应,我们需要创建一个适配 yao 的 fetcher:

  • 在发出请求时自动的增加 header authorization token.
  • 处理 yao 返回的数据格式,将数据和状态封装成 amis 需要的格式,如果返回格式没有问题,直接返回。
  • /api 请求直接返回。
  • 在返回时,需要返回 promise 对象,这样自定义的 adopter 才能生效。
  • 增加出错处理,如果没有权限,重定位到定向到登录页。
  • 处理跨域时自动的取消 withCredentials 请求。
js
fetcher: ({ url, method, data, config, headers }) => {
  config = config || {};
  config.headers = config.headers || headers || {};

  //使用token
  let token = getCookie('token');

  config.withCredentials = true;
  try {
    const url2 = new URL(url);
    //跨域
    //后端可能会设置:Access-Control-Allow-Origin:'*',与withCredentials会有冲突
    if (
      url2.port !== window.location.port ||
      url2.host !== window.location.host ||
      url2.protocol != window.location.protocol
    ) {
      //使用studio
      token = getCookie('studio');

      config.withCredentials = false;
    }
  } catch (error) {}
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  } else {
    window.location.href = 'login.html';
    return;
  }
  const catcherr = (error) => {
    if (error.response.data && error.response.data.message) {
      error.message = error.response.data.message;
    }
    if (error.response) {
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
      if (error.response.data.message === 'Invalid token') {
        window.location.href = 'login.html';
      }
    } 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);
    }

    return new Promise(function (resolve, reject) {
      reject(error);
    });
  };
  const check = (response) => {
    if (
      response.data &&
      response.data.data &&
      response.data.msg &&
      response.data.status != null &&
      response.data.status != undefined
    ) {
      return new Promise(function (resolve, reject) {
        resolve(response);
      });
    }
    // debugger;
    // const url = new URL(response.config.url);
    const path = response.config.url;

    if (!path.startsWith('api')) {
      return new Promise(function (resolve, reject) {
        resolve(response);
      });
    }

    //组成新的payload,即是修改response的数据
    let payload = {
      status: !response.data.code ? 0 : response.data.code,
      msg: response.data.message ? response.data.message : '',
      data: response.data,
    };
    response.data = payload;
    // 在这个回调函数中返回一个新的 Promise 对象
    return new Promise(function (resolve, reject) {
      // 这里应该返回一个新的response,可以在下一个adapter里使用
      // 执行异步操作
      // 在异步操作完成后调用 resolve 或 reject
      resolve(response);
    });
  };
  if (method !== 'post' && method !== 'put' && method !== 'patch') {
    if (data) {
      config.params = data;
    }
    return axios[method](url, config).then(check).catch(catcherr);
  } else if (data && data instanceof FormData) {
    // config.headers = config.headers || {};
    // config.headers['Content-Type'] = 'multipart/form-data';
  } else if (
    data &&
    typeof data !== 'string' &&
    !(data instanceof Blob) &&
    !(data instanceof ArrayBuffer)
  ) {
    data = JSON.stringify(data);
    config.headers['Content-Type'] = 'application/json';
  }

  return axios[method](url, data, config).then(check).catch(catcherr);
};