【问题标题】:Calling setInterval multiple times then Clearing interval , polling not stopped多次调用 setInterval 然后清除间隔,轮询未停止
【发布时间】: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(),并在函数执行后递归调用它。

标签: javascript setinterval polling


【解决方案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 不,这根本不清楚。当您关闭文档时,一页的代码将停止执​​行。我真的不知道你在说什么,我担心我没有时间进一步挖掘它。这个社区的答案是为了引导您找到解决您的错字/脑放屁的方法。
  • "关闭文档时一页的代码将停止执​​行",此语句在单页应用程序中是错误的。即使您导航到另一个页面,轮询也不会在没有明确停止的情况下停止。是的,我知道这个“这个社区的答案是引导你找到解决你的错字/脑放屁的方法”。这个问题发生在我的应用程序中,这就是我问的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
相关资源
最近更新 更多