function withTimeout(promise, timeout, resolveTimeout) {
        var wrapper = new $.Deferred();

        var timer = window.setTimeout(function () {
            if (resolveTimeout) {
                wrapper.resolve();
            } else {
                wrapper.reject(ERROR_TIMEOUT);
            }
        }, timeout);
        promise.always(function () {
            window.clearTimeout(timer);
        });

        // If the wrapper was already rejected due to timeout, the Promise's calls to resolve/reject
        // won't do anything
        promise.then(wrapper.resolve, wrapper.reject);

        return wrapper.promise();
    }
Adds timeout-driven termination to a Promise: returns a new Promise that is resolved/rejected when
the given original Promise is resolved/rejected, OR is resolved/rejected after the given delay -
whichever happens first.

If the original Promise is resolved/rejected first, done()/fail() handlers receive arguments
piped from the original Promise. If the timeout occurs first instead, then resolve() or
fail() (with Async.ERROR_TIMEOUT) is called based on value of resolveTimeout.

@param {$.Promise} promise
@param {number} timeout
@param {boolean=} resolveTimeout If true, then resolve deferred on timeout, otherwise reject. Default is false.
@return {$.Promise}