function doSequentially(items, beginProcessItem, failAndStopFast) {

        var masterDeferred = new $.Deferred(),
            hasFailed = false;

        function doItem(i) {
            if (i >= items.length) {
                if (hasFailed) {
                    masterDeferred.reject();
                } else {
                    masterDeferred.resolve();
                }
                return;
            }

            var itemPromise = beginProcessItem(items[i], i);

            itemPromise.done(function () {
                doItem(i + 1);
            });
            itemPromise.fail(function () {
                if (failAndStopFast) {
                    masterDeferred.reject();
                    // note: we do NOT process any further items in this case
                } else {
                    hasFailed = true;
                    doItem(i + 1);
                }
            });
        }

        doItem(0);

        return masterDeferred.promise();
    }
Executes a series of tasks in serial (task N does not begin until task N-1 has completed).
Returns a "master" Promise that is resolved once all the tasks have resolved. If one or more
tasks fail, behavior depends on the failAndStopFast flag:
  - If true, the master Promise is rejected as soon as the first task fails. The remaining
    tasks are never started (the serial sequence is stopped).
  - If false, the master Promise is rejected after all tasks have completed.

If nothing fails:
 M  ------------d
 1 >---d        .
 2     >--d     .
 3        >--d  .
 4           >--d

With failAndStopFast = false:
 M  ------------F
 1 >---d     .  .
 2     >--d  .  .
 3        >--F  .
 4           >--d

With failAndStopFast = true:
 M  ---------F
 1 >---d     .
 2     >--d  .
 3        >--F
 4          (#4 never runs)

To perform task-specific work after an individual task completes, attach handlers to each
Promise before beginProcessItem() returns it.

@param {!Array.<*>} items
@param {!function(*, number):Promise} beginProcessItem
@param {!boolean} failAndStopFast
@return {$.Promise}