Path: blob/trunk/third_party/closure/goog/async/run.js
2868 views
// Copyright 2013 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314goog.provide('goog.async.run');1516goog.require('goog.async.WorkQueue');17goog.require('goog.async.nextTick');18goog.require('goog.async.throwException');192021/**22* Fires the provided callback just before the current callstack unwinds, or as23* soon as possible after the current JS execution context.24* @param {function(this:THIS)} callback25* @param {THIS=} opt_context Object to use as the "this value" when calling26* the provided function.27* @template THIS28*/29goog.async.run = function(callback, opt_context) {30if (!goog.async.run.schedule_) {31goog.async.run.initializeRunner_();32}33if (!goog.async.run.workQueueScheduled_) {34// Nothing is currently scheduled, schedule it now.35goog.async.run.schedule_();36goog.async.run.workQueueScheduled_ = true;37}3839goog.async.run.workQueue_.add(callback, opt_context);40};414243/**44* Initializes the function to use to process the work queue.45* @private46*/47goog.async.run.initializeRunner_ = function() {48// If native Promises are available in the browser, just schedule the callback49// on a fulfilled promise, which is specified to be async, but as fast as50// possible. Use goog.global.Promise instead of just Promise because the51// relevant externs may be missing, and don't alias it because this could52// confuse the compiler into thinking the polyfill is required when it should53// be treated as optional.54if (String(goog.global.Promise).indexOf('[native code]') != -1) {55var promise = goog.global.Promise.resolve(undefined);56goog.async.run.schedule_ = function() {57promise.then(goog.async.run.processWorkQueue);58};59} else {60goog.async.run.schedule_ = function() {61goog.async.nextTick(goog.async.run.processWorkQueue);62};63}64};656667/**68* Forces goog.async.run to use nextTick instead of Promise.69*70* This should only be done in unit tests. It's useful because MockClock71* replaces nextTick, but not the browser Promise implementation, so it allows72* Promise-based code to be tested with MockClock.73*74* However, we also want to run promises if the MockClock is no longer in75* control so we schedule a backup "setTimeout" to the unmocked timeout if76* provided.77*78* @param {function(function())=} opt_realSetTimeout79*/80goog.async.run.forceNextTick = function(opt_realSetTimeout) {81goog.async.run.schedule_ = function() {82goog.async.nextTick(goog.async.run.processWorkQueue);83if (opt_realSetTimeout) {84opt_realSetTimeout(goog.async.run.processWorkQueue);85}86};87};888990/**91* The function used to schedule work asynchronousely.92* @private {function()}93*/94goog.async.run.schedule_;959697/** @private {boolean} */98goog.async.run.workQueueScheduled_ = false;99100101/** @private {!goog.async.WorkQueue} */102goog.async.run.workQueue_ = new goog.async.WorkQueue();103104105if (goog.DEBUG) {106/**107* Reset the work queue. Only available for tests in debug mode.108*/109goog.async.run.resetQueue = function() {110goog.async.run.workQueueScheduled_ = false;111goog.async.run.workQueue_ = new goog.async.WorkQueue();112};113}114115116/**117* Run any pending goog.async.run work items. This function is not intended118* for general use, but for use by entry point handlers to run items ahead of119* goog.async.nextTick.120*/121goog.async.run.processWorkQueue = function() {122// NOTE: additional work queue items may be added while processing.123var item = null;124while (item = goog.async.run.workQueue_.remove()) {125try {126item.fn.call(item.scope);127} catch (e) {128goog.async.throwException(e);129}130goog.async.run.workQueue_.returnUnused(item);131}132133// There are no more work items, allow processing to be scheduled again.134goog.async.run.workQueueScheduled_ = false;135};136137138