为啥这个回调会产生无限循环
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);
);
);
【讨论】:
以上是关于为啥这个回调会产生无限循环的主要内容,如果未能解决你的问题,请参考以下文章