多次调用 setInterval 然后清除间隔,轮询未停止
Posted
技术标签:
【中文标题】多次调用 setInterval 然后清除间隔,轮询未停止【英文标题】:Calling setInterval multiple times then Clearing interval , polling not stopped 【发布时间】:2018-10-19 06:03:11 【问题描述】:因为我的循环太快了,所以间隔是重叠的,无法停止一个 timerId。这是我的代码:
data = ['115536', '117202']; // BARCODES AVAILABLE ON A4 SHEET //
var scan_delay = 500; // USER AVG SCANNING SPEED PER BARCODE //
var timerId;
var scannedItemsList = []; // ITEMS WHICH ARE SCANNED BY SEEING A4 SHEET BY THE USER //
var tableDataList = []; // TO SHOW DATA WHICH WE GOT FROM API //
Jbin
try
var data = ['115536', '117202']; // BARCODES AVAILABLE ON A4 SHEET //
var scan_delay = 500; // USER AVG SCANNING SPEED PER BARCODE //
var timerId;
var scannedItemsList = []; // ITEMS WHICH ARE SCANNED BY SEEING A4 SHEET BY THE USER //
var tableDataList = []; // TO SHOW DATA WHICH WE GOT FROM API //
execute(data);
function execute(data)
var i = 0;
scanSimulatorWithADelay(data, i);
function scanSimulatorWithADelay(data, i)
setTimeout(function ()
getJobDetailsByCallingAPI(data[i], i);
i++;
if (data.length > i)
scanSimulatorWithADelay(data, i);
else
i = 0;
, scan_delay);
function getJobDetailsByCallingAPI(jobNumber, index)
scannedItemsList.push(jobNumber);
//poll_for_jobs_count_which_are_scanned_but_waiting_to_add_to_table
startPolling();
//Simulate API to get response after every 3 seconds//
var apiDelay = (index + 1) * 3000;
setTimeout(function ()
console.log('API CALLED AT ' + new Date().toLocaleTimeString());
CallTheAPI(jobNumber);
, apiDelay);
function CallTheAPI(jobNumber)
console.log("JOB NO " + jobNumber + " API response Recd");
tableDataList.push(jobNumber);
function startPolling()
var pollStatus = '';
timerId = setInterval(() =>
debugger;
console.log('timerId when starting interval ' + timerId);
var jobsWhichAreScannedButNotLoaded = jobsWhichAreScannedButNotLoadedStill();
console.log("$$$$$$ jobsWhichAreScannedButNotLoaded = " + jobsWhichAreScannedButNotLoaded.length);
if (jobsWhichAreScannedButNotLoaded.length === 0)
console.log("@@@ Inteval Cleared @@@ " + timerId);
//CLEAR TIMER
clearInterval(timerId);
else
pollStatus = 'Polling inprogress and the pollID ' + timerId;
console.log('####' + pollStatus);
, 2000);
function jobsWhichAreScannedButNotLoadedStill()
let stillLoadingJobs = [];
scannedItemsList.forEach(scannedItemsListJobNumber =>
let foundJobInsideTable = false;
if (scannedItemsListJobNumber)
foundJobInsideTable = tableDataList.indexOf(scannedItemsListJobNumber) > -1;
if (!foundJobInsideTable)
stillLoadingJobs.push(scannedItemsListJobNumber);
); // End of scannedItemsList forEach loop
if (stillLoadingJobs.length > 0)
return stillLoadingJobs;
return [];
catch (error) throw error;
【问题讨论】:
这就是为什么你不应该使用setInterval()
。请改用setTimeout()
,并在函数执行后递归调用它。
【参考方案1】:
您的 timer_id
变量位于全局范围内,因此每次调用 startPolling
时都会被覆盖。
所以当你调用clearInterval(timer_id)
时,timer_id
将是最后一个setInterval
的 id,而第一个会一直运行下去。
只需在您的 startPolling
函数中添加一个 var
,以便正确地确定 timer_id
的范围,并且它不会被下次调用覆盖。
try var data = ['115536', '117202'];
var scan_delay = 500;
// remove this one
//var timerId;
var scannedItemsList = [];
var tableDataList = [];
execute(data);
function execute(data)
var i = 0;
scanSimulatorWithADelay(data, i);
function scanSimulatorWithADelay(data, i)
setTimeout(function ()
getJobDetailsByCallingAPI(data[i], i);
i++;
if (data.length > i)
scanSimulatorWithADelay(data, i);
else
i = 0;
, scan_delay);
function getJobDetailsByCallingAPI(jobNumber, index)
scannedItemsList.push(jobNumber);
//poll_for_jobs_count_which_are_scanned_but_waiting_to_add_to_table
startPolling();
//Simulate API to get response after every 3 seconds//
var apiDelay = (index + 1) * 3000;
setTimeout(function ()
console.log('API CALLED AT ' + new Date().toLocaleTimeString());
CallTheAPI(jobNumber);
, apiDelay) ;
function CallTheAPI(jobNumber)
$.ajax(
url: "https://jsonplaceholder.typicode.com/todos/1",
type: "GET",
async: true,
success: function (response)
console.log("JOB NO " + jobNumber + " API response Recd");
tableDataList.push(jobNumber);
);
function startPolling()
var pollStatus = '';
/////////
///HERE
/////////
// Declare timerId in startPolling scope
/////////
var timerId = setInterval(() =>
debugger;
console.log('timerId when starting interval '+ timerId);
var jobsWhichAreScannedButNotLoaded = jobsWhichAreScannedButNotLoadedStill();
console.log("$$$$$$ jobsWhichAreScannedButNotLoaded = "+ jobsWhichAreScannedButNotLoaded.length);
if (jobsWhichAreScannedButNotLoaded.length === 0)
console.log("@@@ Inteval Cleared @@@ "+ timerId);
//CLEAR TIMER
clearInterval(timerId);
else
pollStatus = 'Polling inprogress and the pollID ' + timerId;
console.log('####' + pollStatus);
, 2000);
function jobsWhichAreScannedButNotLoadedStill()
let stillLoadingJobs = [];
scannedItemsList.forEach(scannedItemsListJobNumber =>
let foundJobInsideTable = false;
if (scannedItemsListJobNumber)
foundJobInsideTable = tableDataList.indexOf(scannedItemsListJobNumber) > -1;
if (!foundJobInsideTable)
stillLoadingJobs.push(scannedItemsListJobNumber);
); // End of scannedItemsList forEach loop
if (stillLoadingJobs.length > 0)
return stillLoadingJobs;
return [];
catch (error) throw error;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
【讨论】:
如果我导航到另一个页面,轮询器仍在执行。 @Abhi 你是什么意思?这里?在这个答案中运行代码段? 我在 scan.html 中插入了我的代码并扫描了 500 个工作编号,当逻辑仍在执行时,我正在导航到 search.html。当我检查控制台时。投票仍在进行中。由于我的应用程序是单页,并且我正在使用 scan.html 的破坏方法仍然没有停止。我将所有 pollids 保存在一个列表中,当用户从 scan.html 导航时,将触发 destroy 方法,在 destroy 方法内我循环保存的 pollIds 并调用 clearInterval(pillId)。还是没有运气 @Abhi 不,这根本不清楚。当您关闭文档时,一页的代码将停止执行。我真的不知道你在说什么,我担心我没有时间进一步挖掘它。这个社区的答案是为了引导您找到解决您的错字/脑放屁的方法。 "关闭文档时一页的代码将停止执行",此语句在单页应用程序中是错误的。即使您导航到另一个页面,轮询也不会在没有明确停止的情况下停止。是的,我知道这个“这个社区的答案是引导你找到解决你的错字/脑放屁的方法”。这个问题发生在我的应用程序中,这就是我问的原因。以上是关于多次调用 setInterval 然后清除间隔,轮询未停止的主要内容,如果未能解决你的问题,请参考以下文章
在if语句中添加window.location时,setInterval会冻结