123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- define([
- 'underscore',
- 'domReady!'
- ], function (_) {
- 'use strict';
- var context = require.s.contexts._,
- execCb = context.execCb,
- registry = context.registry,
- callbacks = [],
- retries = 10,
- updateDelay = 1,
- ready,
- update;
- /**
- * Checks if provided callback already exists in the callbacks list.
- *
- * @param {Object} callback - Callback object to be checked.
- * @returns {Boolean}
- */
- function isSubscribed(callback) {
- return !!_.findWhere(callbacks, callback);
- }
- /**
- * Checks if provided module is rejected during load.
- *
- * @param {Object} module - Module to be checked.
- * @return {Boolean}
- */
- function isRejected(module) {
- return registry[module.id] && (registry[module.id].inited || registry[module.id].error);
- }
- /**
- * Checks if provided module has unresolved dependencies.
- *
- * @param {Object} module - Module to be checked.
- * @returns {Boolean}
- */
- function isPending(module) {
- if (!module.depCount) {
- return false;
- }
- return module.depCount > _.filter(module.depMaps, isRejected).length;
- }
- /**
- * Checks if requirejs's registry object contains pending modules.
- *
- * @returns {Boolean}
- */
- function hasPending() {
- return _.some(registry, isPending);
- }
- /**
- * Checks if 'resolver' module is in ready
- * state and that there are no pending modules.
- *
- * @returns {Boolean}
- */
- function isReady() {
- return ready && !hasPending();
- }
- /**
- * Invokes provided callback handler.
- *
- * @param {Object} callback
- */
- function invoke(callback) {
- callback.handler.call(callback.ctx);
- }
- /**
- * Sets 'resolver' module to a ready state
- * and invokes pending callbacks.
- */
- function resolve() {
- ready = true;
- callbacks.splice(0).forEach(invoke);
- }
- /**
- * Drops 'ready' flag and runs the update process.
- */
- function tick() {
- ready = false;
- update(retries);
- }
- /**
- * Adds callback which will be invoked
- * when all of the pending modules are initiated.
- *
- * @param {Function} handler - 'Ready' event handler function.
- * @param {Object} [ctx] - Optional context with which handler
- * will be invoked.
- */
- function subscribe(handler, ctx) {
- var callback = {
- handler: handler,
- ctx: ctx
- };
- if (!isSubscribed(callback)) {
- callbacks.push(callback);
- if (isReady()) {
- _.defer(tick);
- }
- }
- }
- /**
- * Checks for all modules to be initiated
- * and invokes pending callbacks if it's so.
- *
- * @param {Number} [retry] - Number of retries
- * that will be used to repeat the 'update' function
- * invokation in case if there are no pending requests.
- */
- update = _.debounce(function (retry) {
- if (!hasPending()) {
- retry ? update(--retry) : resolve();
- }
- }, updateDelay);
- /**
- * Overrides requirejs's original 'execCb' method
- * in order to track pending modules.
- *
- * @returns {*} Result of original method call.
- */
- context.execCb = function () {
- var exported = execCb.apply(context, arguments);
- tick();
- return exported;
- };
- return subscribe;
- });
|