防止AXIOS多个调用

sd2nnvve  于 2022-10-21  发布在  iOS
关注(0)|答案(3)|浏览(139)

我在我的VueJS应用程序中使用AXIOS。目前,在每个组件中,我在每个组件中使用一个变量来检查用户在启动axios调用之前是否已经单击了按钮。这会导致大量重复的代码,所以我考虑将AXIOS调用 Package 成一个函数“Unique eAxios”,如下所示:

const urlsAPI = [];
const uniqueAxios = async (method, url, data) => {
  if (urlsAPI.includes(url)) {
    console.log('Already called!!');
    Promise.reject(new Error('Already called'));
  } else {
    urlsAPI.push(url);
    await axios[method](url, data)
      .then((res) => {
        console.log('OK');
        console.log(res);
        return Promise.resolve(res);
      })
      .catch((e) => {
        console.log('KO');
        console.log(e);
        return Promise.reject(e);
      });
  }
};

但当我在组件中使用此函数时,如下所示:

await uniqueAxios(
          'post',
          `${process.env.VUE_APP_API_URL}/XXX`,
        )
          .then((res) => {
            console.log(res);
          })
          .catch((e) => {
            console.log(e);

控制台抛出错误:TypeError: res is undefined。不过,已经联系了API。只是我不能处理我以前直接使用axios时的thencatch
我肯定 Package uniqueAxios函数不正确。有人知道我应该怎么处理这件事吗?先谢谢你。

svmlkihl

svmlkihl1#

您的原始代码

const urlsAPI = [];

const uniqueAxios = async (method, url, data) => {
  if (urlsAPI.includes(url)) {
    console.log('Already called!!');
    Promise.reject(new Error('Already called'));
  } else {
    urlsAPI.push(url);
    await axios[method](url, data)
      .then((res) => {
        console.log('OK');
        console.log(res);
        return Promise.resolve(res);
      })
      .catch((e) => {
        console.log('KO');
        console.log(e);
        return Promise.reject(e);
      });
  }
};

所有async函数都返回承诺,甚至类似于:

async function three() {
  return 3;
}

或者这个

async function belch() {
  throw new Error("Belch!");
}

它将根据是否引发错误来解决或拒绝。
因为您没有显式返回值,所以返回值是一个承诺,解析为undefined(除非抛出错误,在这种情况下它会拒绝)。
您的代码将会更干净(并且可以工作!)如果你只是说这样的话:

const inFlightUrls = new Set();

const uniqueAxios = async (method, url, data) => {

  const inflight = inFlightUrls.has(url);
  if (inFlight) {
    throw new Error('Already called');
  }

  inFlightUrls.add(url);

  const res = axios[method](url, data)
              .finally( () => inflightUrls.delete(url) ) ;

  return res ;
};

上面的函数返回一个承诺,该承诺要么使用Axios响应对象进行解析,要么拒绝并返回错误(来自Axios或由您抛出)。

vsikbqxv

vsikbqxv2#

[编辑:它有效,但我选择的答案要好得多]
事实上,我找到了一个解决方案:

let urlsAPI = [];
const uniqueAxios = async (method, url, data) => {
  if (urlsAPI.includes(url)) {
    throw new Error('Axios already called');
  }
  urlsAPI.push(url);
  const t = {
    type: 0,
    content: null,
  };
  await axios[method](url, data)
    .then((res) => {
      t.content = res;
      t.type = 1;
    })
    .catch((e) => {
      t.content = e;
    })
    .finally(() => {
      urlsAPI = urlsAPI.filter((u) => u !== url);
    });
  if (t.type) {
    return t.content;
  }
  throw t.content;
};
holgip5t

holgip5t3#

您有多个问题,第一个是在您的函数中不返回任何内容。

const uniqueAxios = async (method, url, data) => {
  if (urlsAPI.includes(url)) {
    console.log('Already called!!');
    Promise.reject(new Error('Already called'));
  } else {
    urlsAPI.push(url);
    return await axios[method](url, data) // You need to return the axios
      .then((res) => {
        console.log('OK');
        console.log(res);
        return Promise.resolve(res); // This line return inside the promise axios not the function
      })
      .catch((e) => {
        console.log('KO');
        console.log(e);
        return Promise.reject(e);
      });
  }
};

第二件事就是你等待着,然后白白地做了一次。现在,有了这个更改,您可以像这样等待您的函数并记录响应。

const response = await uniqueAxios(
  'post',
  `${process.env.VUE_APP_API_URL}/XXX`,
  )
console.log(response)

相关问题