javascript - 获取和获取重试的拦截器? (Javascript)

标签 javascript interceptor

我正在尝试为 javascript 中的 fetch 创建一个拦截器( react 更具体)。它应该从每个被调用的 fetch 中获取结果,如果是 401 错误,它应该启动对另一个路由的新 fetch 调用以获取 cookie(刷新 token )。然后,应该再次尝试原始的 fetch 调用(因为现在用户已登录)。
我已经成功地触发了新的 fetch 调用并为每个调用发回了 cookie,但是我在下面遇到了这两个问题:

  • 我现在不知道如何在收到刷新 token 后重试 fetch 调用。那可能吗?我找到了 fetch-retry npm ( https://www.npmjs.com/package/fetch-retry ),但不确定在应该为原始 fetch 调用完成时如何以及是否可以在拦截器上实现它。
  • 我似乎对 async await 做错了(我认为),因为拦截在返回数据之前没有等待 fetch 调用(原始 fetch 上的状态码似乎是 401 而不是 200 应该是我们得到cookie。我还尝试在拦截器内返回 fetch 的响应,但返回的是未定义的)。

  • 关于如何解决这个问题的任何想法?有人做过类似的事情吗?
    下面是我的代码:
    (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
    
          }); 
      };
    })();
    
    编辑 : 为了更清楚我的追求。我需要一个像上面描述的拦截器才能工作,所以我不必在每次 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();
        };
    
    所以基本上拦截器应该:
  • 检查是否有401,如果有则:
  • 获取 api/ token
  • 如果 api/token 返回 401,它应该只返回那个。
  • 如果 api/token 返回 200,它应该再次运行原始提取
  • 最佳答案

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

    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);
    })();

  • Example1 向 api 发出 404 状态请求,这将导致 404 条件运行,然后调用 200 api,之后将返回响应
  • Example2 对 200 api 的请求将返回 200 状态代码,这将导致 200 条件通过并运行并返回响应
  • Example3 向 api 发出 401 状态的请求,这将导致 401 条件通过,然后调用 200 api 并打印响应,之后它将脱离条件,您可以设置 token ,然后将其用于另一个获取请求
  • 关于javascript - 获取和获取重试的拦截器? (Javascript),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65638438/

    相关文章:

    Javascript:调用不属于对象的方法

    javascript - 滚动回到顶部链接在第一次加载时可见

    javascript - 将水线模型属性设置为默认值

    c# - 使用 Autofac 拦截 .NET Core 2.0 Web API Controller

    Javascript同时执行两个函数1(onclick事件)

    javascript - 忽略一段javascript的设备

    c# - 在 CaSTLe Windsor 中,我可以注册一个接口(interface)组件并获得实现的代理吗?

    java - 在 Struts 2 中使用拦截器时出现 NullPointerException

    javascript - Node.js 中的拦截器

    java - Hibernate 拦截器中的方法 post Flush 出错