用于获取和获取重试的拦截器?(Javascript)

Hej*_*123 7 javascript interceptor

我正在尝试创建一个用于在 javascript 中获取的拦截器(更具体地说是 React)。它应该从每次调用的 fetch 中获取结果,如果是 401 错误,则应该向另一个路由发起新的 fetch 调用以获取 cookie(刷新令牌)。然后,应再次尝试原始的提取调用(因为现在用户已登录)。

我已经成功触发新的 fetch 调用并发回每个调用的 cookie,但是我遇到了以下两个问题:

  1. 我现在不知道如何在收到刷新令牌后重试 fetch 调用。那可能吗?我找到了 fetch-retry npm ( https://www.npmjs.com/package/fetch-retry ),但不确定如何以及是否可以在拦截器上实现它,当它应该为原始的 fetch 调用完成时。

  2. 我似乎在异步等待方面做错了(我认为),因为拦截在返回数据之前没有等待提取调用(原始提取上的状态代码似乎是 401 而不是 200,在我们得到之后它应该是cookie。我还尝试返回拦截器内获取的响应,但返回未定义)。

知道如何解决这个问题吗?有谁做过类似的事情吗?

下面是我的代码:

(function () {
  const originalFetch = fetch;
  fetch = function() {
      return originalFetch.apply(this, arguments).then(function(data) {

          if(data.status === 401) {
            console.log('not authorized, trying to get refresh cookie..')

            const fetchIt = async () => {
              let response = await fetch(`/api/token`, {
                  method: 'POST',
                  credentials: 'include', 
                  headers: {
                      'Content-Type': 'application/json'
                  },
              });
          }
        fetchIt();
          } 
         return data

      }); 
  };
})();
Run Code Online (Sandbox Code Playgroud)

编辑:为了更清楚我的追求。我需要一个像上面描述的那样的拦截器才能工作,所以我不必在每次 fetch 调用后都执行类似的操作:

getData() {
        const getDataAsync = async () => {
            let response = await fetch(`/api/loadData`, { method: 'POST' });

           if(response.status === 401) {
            let responseT = await fetch(`/api/token`, {
                method: 'POST',
                credentials: 'include', 
                headers: {
                    'Content-Type': 'application/json'
                },
            });

            if(responseT.status === 401) {
                return responseT.status
            }

            if(responseT.status === 200) {
            response = await fetch(`/api/loadData`, { method: 'POST' });
            }
           }

          let data = await response.json();
            //Do things with data
        };
        getDataAsync();
    };
Run Code Online (Sandbox Code Playgroud)

所以基本上拦截器应该:

  1. 检查是否有401,如果有则:
  2. 获取API/令牌
  3. 如果 api/token 返回 401,它应该只返回该值。
  4. 如果 api/token 返回 200,则应再次运行原始 fetch

Cha*_*dan 5

您可以简单地使用originalFetch令牌并等待响应,如果响应为 401,那么您只需将空响应返回到第一个 fetch 调用,否则您更新了令牌,然后让它进入下一个条件,该条件将重新运行旧请求。

let TEMP_API = {
  '401': {
    url: 'https://run.mocky.io/v3/7a98985c-1e59-4bfb-87dd-117307b6196c',
    args: {}
  },
  '200': {
    url: 'https://jsonplaceholder.typicode.com/todos/2',
    args: {}
  },
  '404': {
    url: 'https://jsonplaceholder.typicode.com/todos/1',
    args: {
      method: "POST",
      credentials: "include"
    }
  }
}

const originalFetch = fetch;
fetch = function() {
  let self = this;
  let args = arguments;
  return originalFetch.apply(self, args).then(async function(data) {
    if (data.status === 200) console.log("---------Status 200----------");
    if (data.status === 401) {
      // request for token with original fetch if status is 401
      console.log('failed');
      let response = await originalFetch(TEMP_API['200'].url, TEMP_API['200'].args);
      // if status is 401 from token api return empty response to close recursion
      console.log("==========401 UnAuthorize.=============");
      console.log(response);
      if (response.status === 401) {
        return {};
      }
      // else set token
      // recall old fetch
      // here i used 200 because 401 or 404 old response will cause it to rerun
      // return fetch(...args); <- change to this for real scenarios
      // return fetch(args[0], args[1]); <- or to this for real sceaerios
      return fetch(TEMP_API['200'].url, TEMP_API['200'].args);
    }
    // condition will be tested again after 401 condition and will be ran with old args
    if (data.status === 404) {
      console.log("==========404 Not Found.=============");
      // here i used 200 because 401 or 404 old response will cause it to rerun
      // return fetch(...args); <- change to this for real scenarios
      // return fetch(args[0], args[1]); <- or to this for real scenarios
      return fetch(TEMP_API['200'].url, TEMP_API['200'].args);
sceaerios
    } else {
      return data;
    }
  });
};

(async function() {
  console.log("==========Example1=============");
  let example1 = await fetch(TEMP_API['404'].url, TEMP_API['404'].args);
  console.log(example1);
  console.log("==========Example2=============");
  let example2 = await fetch(TEMP_API['200'].url, TEMP_API['200'].args);
  console.log(example2);
  console.log("==========Example3=============");
  let example3 = await fetch(TEMP_API['401'].url, TEMP_API['401'].args);
  console.log(example3);
})();
Run Code Online (Sandbox Code Playgroud)

  1. 示例 1 向 api 发出 404 状态请求,这将导致 404 条件运行,然后调用 200 api,之后将返回响应
  2. 示例2 对 200 api 发出的请求将返回 200 状态代码,这将导致 200 条件通过并运行并返回响应
  3. 示例3向api发出401状态请求,这将导致401条件通过,然后调用200 api并打印响应,之后它将超出条件,您可以设置令牌,然后将在另一个获取请求中使用该令牌