I'm brand new here, but I've read the guidelines and looked at some up-voted questions. Hopefully I understand how I'm supposed to do this... if not, please let me know and I'll fix my question. ExplanationI have written a simple javascript plugin of sorts. It takes the settings object for a jQuery.ajax request and a few options (frequency, failure tolerance, etc) and then periodically issues the ajax request. If the request fails, it increases the interval to the next request. If success follows a number of failures, the interval is slowly reduced to reach the original frequency. Usage looks something like this:var ajax = {url: 'example.com', success: mySuccessFunc};var cw = Coward(ajax, {}); // Request my url with default settingscw.Start();... // Coward is running, refreshes happening periodically cw.Stop(); Purpose of ReviewI'm open to any feedback about my code that you're willing to give me. However, I came here seeking a few things specifically: Are there any bugs that will result in an excessive number of requests or other undesirable behavior? Am I doing anything unsafe? Race conditions?JSLint warns me about scope in a few places, but the code works. Am I violating standards? Should I be handling scope differently (particularly with the 'underscore' functions and the 'live variables')? The Code// Coward - One time or periodic refresh that retreats if anything goes wrong.//// This tool was designed for use with jQuery 1.9 or later//// Written by Adam Jensenfunction Coward(userReq, custom) {  'use strict';//==============================================// Options and variables used by the coward// - Do not change `opts` after invocation -//==============================================  // Combine user options with our defaults  var opts = $.extend({        frequency: 1000, // How often to issue ajax request        ceiling: 10,     // After this number of failures, multiple will not be applied        multiple: 1.5,   // Multiplier applied to        infinite: false, // If false, coward will stop running when ceiling is passed        verbose: false   // If true, messages will appear in console log      }, custom);  // Live Variables (these will change as the code runs  // and be reset at restart)  var running = false;  var fails = 0;  var next = opts.frequency;  var nextId = ;  // Save out user's callbacks to be executed at the proper time  if (userReq.hasOwnProperty('success')) {    var successCallback = userReq.success;    delete userReq.success;  }  if (userReq.hasOwnProperty('error')) {    var errorCallback = userReq.error;    delete userReq.error;  }  // Combine user request sans callbacks with our default request  var request = $.extend({        url: 'localhost',        method: 'GET',        timeout: 3000,        success: _success,        error: _fail      }, userReq);  // Make sure we're not going to accidentally DoS someone  if (opts.multiple < 1) {    // multiple less than one results in increasing frequency on fail    _log(Multiple CANNOT be less than one!);    return false; // Lack of a callable will throw an error in users code  }//==========================================================// Main body of Coward (_run, _success, _fail)// - DO NOT export these functions directly -// - INSTEAD use Start, DelayStart, and Stop -//==========================================================  // _run gives us a point to verify the status of the coward before the ajax call  function _run() {    if (!running) {      return false;    }    $.ajax(request);    return true;  }  // Our own callback used to check status and set next interval  function _success(data, status, jqxhr) {    // If there are failures, start to scale up requests again    if (fails > 0) {      fails--;      next = Math.round(next/opts.multiple);      _log(Success! Recovered a white flag, now have +(opts.ceiling-fails)+. Next attempt in +next);    }    // Set the next interval and call the users callback if set    if (next > 0) {      nextId = setTimeout(_run, next);    }    if (successCallback !== undefined) {      successCallback(data, status, jqxhr);    }  }  function _fail(jqxhr, status, error) {    // If we have fails left, log the incident and continue    if (fails < opts.ceiling) {      next = Math.round(next * opts.multiple);      _log('Refresh failed. '+(opts.ceiling-fails)+' white flags remaining. Retreating to '+next+' [front line at '+opts.frequency+'].');      fails++;      nextId = setTimeout(_run, next);    } else {      if (!opts.infinite) {        // We've passed the ceiling and infinite is not set. Give up.        _log('Refresh has failed more than '+fails+' times. I surrender!');        running = false;      } else {        _log('Failed more than '+fails+' times, ceiling '+opts.ceiling+' prevents increasing multiple.');        nextId = setTimeout(_run, next);      }    }    if (errorCallback !== undefined) {      errorCallback(jqxhr, status, error);    }  }  function _log(msg) {    if (opts.verbose) {      console.log(msg);    }  }//===============================================// Publicly Accessible Functions//===============================================  var Start = function() {    // Reset vars in case of Stop/Start cycle    fails = 0;    next = opts.frequency;    nextId = ;    running = true;    return _run();  };  var DelayStart = function(delay) {    // Start after user provided delay or one frequency cycle    if (delay === undefined) {      setTimeout(Start, opts.frequency);      return opts.frequency;    }    setTimeout(Start, delay);    return delay;  };  var Stop = function() {    // Stop the run function from creating new ajax calls    clearTimeout(nextId);    running = false;    return false;  };  var Status = function() {    return {      Opts: opts,      Next: next,      Fails: fails,      NextId: nextId    };  };  return {    Start: Start,    DelayStart: DelayStart,    Stop: Stop,    Status: Status  };}The code is also available on github.
jQuery AJAX requests - Plugin to Backoff on failure
javascript;jquery;ajax
You should check that the supplied success and error callbacks are functions not just that they exist.if (typeof userReq.success === function) {    var successCallback = userReq.success;    delete userReq.success;}The way you have it now, if a user uses the following configs :var ajax = {url: 'example.com', success: null};var ajax = {url: 'example.com', success: my success function};will cause the check below to pass, resulting in an errorif (successCallback !== undefined) {   successCallback(data, status, jqxhr);}