setTimeout () and setInterval () source code analysis

I recently in the development process because of the need for dynamic rendering pages, do not want to have to refresh the page data, but allows the browser to render dynamically based on customer data, this time used the setInterval function, but this function and setTimeout () compared to what difference does it make? we know:

  • setTimeout () method is bound to a browser window, you can specify a code by this method or function in how many milliseconds (ms) execution, and returns the number of the timer, of course we can cancel the code by clearTimeout () execution
  • setInterval () method to bind in a browser window, you can specify a piece of code or function setInterval by how many milliseconds (ms) the timing of the execution, and returns the number of the timer, of course we can cancel the code by clearInterval () the implementation of
    the most effective and direct is feeling a little experiment under:
    setInterval () method code execution would need to perform is actually added to the task queue until the turn of code is executed, it is determined whether the time has come, if the code is executed arrival
    var startTime=new Date();
    var func = function(){
    console.log('start: ' + (new Date()-startTime));
    for(var i=0; i<1000000000; i++){}
    console.log('end: ' + (new Date()-startTime));
    };
    setInterval(func,1000);

    After executing the above code, you will find setInterval the end and start time beating very large, are not we set 1000ms. Because setInterval is the beginning point calibration execution time, when the registration function (func) over, it will not be fixed 1000ms.
    setTimeout () and setInterval () source code analysis
    setTimeout () usage setInterval substantially the same, except that the timing of the execution, we also performed to test the delay phenomenon

    var startTime=new Date();
    var func = function(){
    console.log('start: ' + (new Date()-startTime));
    for(var i=0; i<1000000000; i++){};
    console.log('end: ' + (new Date()-startTime));
    setTimeout(func,1000);
    };
    setTimeout(func,1000);

    Chart can be found under the observation time setTimeout set interval, because the code is currently executed task queue and delays in the implementation of circumstances that may occur, we can see that the above code, perform the func end and start time interval is basically in line with our set 1000ms
    setTimeout () and setInterval () source code analysis
    look beyond, we might look at the source code for these two functions
    setTimeout () and setInterval () source code analysis
    from the function declaration can know setInterval here allows mass participation, a method allows us pass, let it perform at a certain time (number), the waiting time which depends on the scheduler _scheduler, and performing the method is _fnAndFlushresponsible for regulation, however, as _requeuePeriodicTimera fixed 1000ms presence of this method that the time interval is not provided we

....
case 'setInterval':
  task.data!['handleId'] = this._setInterval(
      task.invoke, task.data!['delay']!,
      Array.prototype.slice.call((task.data as any)['args'], 2));
  break; 
....

private _setInterval(fn: Function, interval: number, args: any[]): number {
  let id = Scheduler.nextId;
  let completers = {onSuccess: null as any, onError: this._dequeuePeriodicTimer(id)};
  let cb = this._fnAndFlush(fn, completers);

  // Use the callback created above to requeue on success.
  completers.onSuccess = this._requeuePeriodicTimer(cb, interval, args, id);

  // Queue the callback and dequeue the periodic timer only on error.
  this._scheduler.scheduleFunction(cb, interval, args, true);
  this.pendingPeriodicTimers.push(id);
  return id;
}  

First look at _fnAndFlushthe code, this function is actually a function of our need to perform brush into memory, waiting for the browser to perform

private _fnAndFlush(fn: Function, completers: {onSuccess?: Function, onError?: Function}):
    Function {
  return (...args: any[]): boolean => {
    fn.apply(global, args);

    if (this._lastError === null) {  // Success
      if (completers.onSuccess != null) {
        completers.onSuccess.apply(global);
      }
      // Flush microtasks only on success.
      this.flushMicrotasks();
    } else {  // Failure
      if (completers.onError != null) {
        completers.onError.apply(global);
      }
    }
    // Return true if there were no errors, false otherwise.
    return this._lastError === null;
  };
}

We might look at the _requeuePeriodicTimerfeatures of this method to complete the function. Its function will exist in the added memory browser execution queue (if present), function-complete process has entered the next execution cycle of the scheduler, i.e., during execution in wait for the next function has a timer function execution. As the experiment, all of the start interval we observe approximately 1000ms

private _requeuePeriodicTimer(fn: Function, interval: number, args: any[], id: number): Function {
  return () => {
    // Requeue the timer callback if it's not been canceled.
    if (this.pendingPeriodicTimers.indexOf(id) !== -1) {
      this._scheduler.scheduleFunction(fn, interval, args, true, false, id);
    }
  };
}

For setTimeout here allows mass participation, allowing one we pass, so that in a certain time (number) After execution, its time to wait depends on the scheduler _scheduler, but the scheduler function is what makes us meet our set time interval the reason for the implementation of 1000ms, and the method by _fnAndFlush is responsible for regulation, because setTimeout will not perform the function pushed into the queue, so the timer will not begin to run until the function after entering the previous cycle were completed the next cycle, as wait experiment code written in 1000ms

...
case 'setTimeout':
  task.data!['handleId'] = this._setTimeout(
      task.invoke, task.data!['delay']!,
      Array.prototype.slice.call((task.data as any)['args'], 2));
  break;
...
private _setTimeout(fn: Function, delay: number, args: any[], isTimer = true): number {
  let removeTimerFn = this._dequeueTimer(Scheduler.nextId);
  // Queue the callback and dequeue the timer on success and error.
  let cb = this._fnAndFlush(fn, {onSuccess: removeTimerFn, onError: removeTimerFn});
  let id = this._scheduler.scheduleFunction(cb, delay, args, false, !isTimer);
  if (isTimer) {
    this.pendingTimers.push(id);
  }
  return id;
}   

Reference:
https://www.jeffjade.com/2016/01/10/2016-01-10-javacript-setTimeout/
https://www.jeffjade.com/2016/01/10/2016-01-10 -javaScript-setInterval /

Guess you like

Origin blog.51cto.com/yerikyu/2434534