为啥这个回调会产生无限循环

Posted

技术标签:

【中文标题】为啥这个回调会产生无限循环【英文标题】:why this call back gives infinity loop为什么这个回调会产生无限循环 【发布时间】:2021-12-19 13:11:32 【问题描述】:

所以我正在学习 javascript 中的 async-await 以及当我尝试执行此回调地狱时(我知道这不是最佳实践,但我必须学习它) 我第二次调用它一直调用自己的函数(无限循环) 您可以运行代码以了解更多信息,因为在我看来没有任何问题我花了过去 2 天试图理解问题,但我最终到了这里

代码:

const xhr = new XMLHttpRequest();
const url = new URL("https://www.breakingbadapi.com/api/quotes");

const moveiData = (link, callBack) => 
  xhr.addEventListener("readystatechange", () => 
    if (xhr.readyState === 4 && xhr.status == 200) 
     else if (xhr.readyState === 4) 
      callBack("could not fetch data");
    
  );

  xhr.open("GET", link);

  xhr.send();
;

moveiData(url, (response) => 
  console.log(response);

  moveiData(url, (response) => 
    console.log(response);
  );
);

【问题讨论】:

您是否在 if 语句中调用了callback()(成功案例)? 不仅如此,每次调用 moveiData 只会添加另一个监听器。 据我所知,您调用了 2 次 moveiData。但是 xhr.addEventListener 正在监听同一个事件两次。你应该在函数之外定义它 【参考方案1】:
const url = new URL("https://www.breakingbadapi.com/api/quotes");

const moveiData = (link, callBack) => 
    const xhr = new XMLHttpRequest();
    xhr.addEventListener("readystatechange", () => 
    if (xhr.readyState === 4 && xhr.status == 200) 
     else if (xhr.readyState === 4) 
      callBack("could not fetch data");
    
  );

  xhr.open("GET", link);
  xhr.send();
;

moveiData(url, (response) => 
  console.log(response);
);

【讨论】:

【参考方案2】:

不要重复使用相同的 XMLHttpRequest 对象。每次调用该函数时声明一个新函数,并确保在有肯定响应时在回调中返回一些数据。

const url = new URL('https://www.breakingbadapi.com/api/quotes');

const moveiData = (link, callBack) => 

  const xhr = new XMLHttpRequest();

  xhr.addEventListener('readystatechange', () => 
    if (xhr.readyState === 4 && xhr.status == 200) 
      callBack(JSON.parse(xhr.response));
     else if (xhr.readyState === 4) 
      callBack('could not fetch data');
    
  );

  xhr.open("GET", link);
  xhr.send();

;

moveiData(url, function (response) 
  console.log(response);
  moveiData(url, function (response) 
    console.log(response);
  );
);

您可能会发现相对较新的fetch API 和the async/await process 有点more rewarding。

const url = 'https://www.breakingbadapi.com/api/quotes';

function getData(url) 
  return fetch(url);


async function main() 
  try 
    const res = await getData(url);
    console.log(await res.json());  
   catch (err) 
    console.log(err);
  


main();

【讨论】:

【参考方案3】:

在那个问题上你有三个选择。

1- 您添加了一个新的事件侦听器,您应该在响应时将其移除。

const xhr = new XMLHttpRequest();
const url = new URL("https://www.breakingbadapi.com/api/quotes");

const moveiData = (link, callBack) => 
  const handler = () => 
    if (xhr.readyState === 4 && xhr.status == 200) 
      xhr.removeEventListener("readystatechange", handler);     
      callBack(JSON.parse(xhr.response));
     else if (xhr.readyState === 4) 
      callBack("could not fetch data");
    
  ;

  const a = xhr.addEventListener("readystatechange", handler);

  xhr.open("GET", link);

  xhr.send();
;

moveiData(url, (response) => 
  console.log(response);

  moveiData(url, (response) => 
    console.log(response);
  );
);

2- 使用 onreadystatechange 回调。

const xhr = new XMLHttpRequest();
const url = new URL("https://www.breakingbadapi.com/api/quotes");

const moveiData = (link, callBack) => 
  xhr.onreadystatechange = () => 
    if (xhr.readyState === 4 && xhr.status == 200)    
      callBack(JSON.parse(xhr.response));
     else if (xhr.readyState === 4) 
      callBack("could not fetch data");
    
  ;

  xhr.open("GET", link);

  xhr.send();
;

moveiData(url, (response) => 
  console.log(response);

  moveiData(url, (response) => 
    console.log(response);

  );
);

3- 为每个函数声明新的 XMLHttpRequest。

const url = new URL('https://www.breakingbadapi.com/api/quotes');
const moveiData = (link, callBack) => 
  const xhr = new XMLHttpRequest();

  xhr.addEventListener('readystatechange', () => 
    if (xhr.readyState === 4 && xhr.status == 200) 
      callBack(JSON.parse(xhr.response));
     else if (xhr.readyState === 4) 
      callBack('could not fetch data');
    
  );

  xhr.open("GET", link);
  xhr.send();
;

moveiData(url, function (response) 
  console.log(response);

  moveiData(url, function (response) 
    console.log(response);
  );
);

【讨论】:

以上是关于为啥这个回调会产生无限循环的主要内容,如果未能解决你的问题,请参考以下文章

有人能告诉我为啥这个方法会进入无限循环吗?

为啥这个 Scanf 会导致无限循环?

为啥这个异步函数无限循环?

为啥这会导致无限循环

为啥以 char 作为索引的循环会无限循环?

为啥这段代码会进入无限循环? [复制]