简体   繁体   中英

How to execute setTimeout function immediately after the delay?

I want to execute setTimeout after the delay and not wait for it to be called from the message queue after all the other functions have executed. Please refer the code below:

let test = function(){ console.log('test') }
setTimeout(() => console.log('hi'), 2000)

test();
test();
test();
.
.
.
.
this code takes more than 2 seconds to execute;

How to get setTimeout after 2 seconds instead of at the end ?

You may not need setTimeout . Instead return a promise from test function and do rest of the things inside then which will only work once test is resolved

 let test = function() { return new Promise(function(resolve, reject) { console.log('test'); resolve('test executed') }) } test().then(function(data) { console.log(data) });

I thought I would mention that if those test() calls do not perform DOM operations you could possibly move them to a worker.

Web Workers allow running code on a background thread that doesn't block your main UI thread. I've created a quick example that runs a synchronous task of arbitrary duration on a worker thread. On the main thread setInterval and setTimeout calls are running uninterrupted.

See it in action.

index.js

let interval = setInterval(() => console.log("Not blocked"), 500);

console.log("Scheduling to run in 2 seconds");
setTimeout(() => {
  console.log("2 seconds passed. Running scheduled task! ");
}, 2000);

let longTaskRunner = new Worker("./src/worker.js");
let taskDuration = 3;
console.log(
  `Starting synchronous task that takes more than ${taskDuration} seconds`
);

longTaskRunner.postMessage(taskDuration);
longTaskRunner.onmessage = function(e) {
  console.log(`Long task completed in ${e.data} seconds`);
  clearInterval(interval);
};
longTaskRunner.onerror = function(e) {
  console.log(e.message);
};

worker.js

self.onmessage = function(e) {
  const runFor = e.data * 1000;
  let startedAt = Date.now();
  let timeElapsed = 0;

  while (timeElapsed < runFor) {
    timeElapsed = Date.now() - startedAt;
  }

  self.postMessage(timeElapsed / 1000);
};

If the chain of test s is consuming more than 2000ms of CPU time synchronously ("blocking"), I don't think it's possible like that - the best you could do is check in test (or in a function wrapped around it) whether the time difference between the start (where your setTimeout is currently) and the current time is more than 2 seconds - if so, execute the function. For example:

console.log('start');
let hasRun = false;
const fnToRunLater = () => console.log('hi');
const startTime = Date.now();
function test() {
  const now = Date.now();
  if (!hasRun && now - startTime > 2000) {
    fnToRunLater();
    hasRun = true;
  }
  for (let i = 0; i < 2e8; i++) {
    // some expensive operations
  }
}
test();
test();
test();
test();
test();
test();
test();
test();
test();
test();
test();
test();
test();
test();
if (!hasRun) {
  fnToRunLater();
}
console.log('done');

(warning: below snippet containing the code above will block your browser for a bit, depending on your hardware)

 // look at the timing in your browser console, not the snippet console console.log('start'); let hasRun = false; const fnToRunLater = () => console.log('hi'); const startTime = Date.now(); function test() { const now = Date.now(); if (!hasRun && now - startTime > 2000) { fnToRunLater(); hasRun = true; } for (let i = 0; i < 2e8; i++) { // some expensive operations } } test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); if (!hasRun) { fnToRunLater(); } console.log('done');

If an individual test takes too long, and the timeout isn't accurate enough (eg, if a test takes 400ms and this takes the difference from 1800ms to 2200ms, and that 200ms of inaccuracy is too much), then you'll have to change the test code so that it does multiple checks inside.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM