多次调用 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 然后清除间隔,轮询未停止的主要内容,如果未能解决你的问题,请参考以下文章

setTimeout ,setInterval

如何在函数内清除此 setInterval?

在if语句中添加window.location时,setInterval会冻结

在 setInterval 中调用 clearInterval() 不会停止 setinterval

setInterval 和 setTimeout 用法

setTimeout和setInterval的区别