@@ -45,6 +45,7 @@ function Analytics() {
4545 this . Integrations = { } ;
4646 this . _integrations = { } ;
4747 this . _readied = false ;
48+ this . _readiedIntegrations = { } ;
4849 this . _timeout = 300 ;
4950 // XXX: BACKWARDS COMPATIBILITY
5051 this . _user = user ;
@@ -106,6 +107,7 @@ Analytics.prototype.init = Analytics.prototype.initialize = function(settings, o
106107
107108 this . _options ( options ) ;
108109 this . _readied = false ;
110+ this . _readiedIntegrations = { } ;
109111
110112 // clean unknown integrations from settings
111113 var self = this ;
@@ -146,8 +148,14 @@ Analytics.prototype.init = Analytics.prototype.initialize = function(settings, o
146148 integration . page = after ( 2 , integration . page ) ;
147149 }
148150
151+ var integrationReady = function ( ) {
152+ self . _readiedIntegrations [ integration . name ] = true ;
153+ self . emit ( integration . name + '-ready' ) ;
154+ ready ( ) ;
155+ } ;
156+
149157 integration . analytics = self ;
150- integration . once ( 'ready' , ready ) ;
158+ integration . once ( 'ready' , integrationReady ) ;
151159 integration . initialize ( ) ;
152160 } , integrations ) ;
153161
@@ -496,14 +504,58 @@ Analytics.prototype.alias = function(to, from, options, fn) {
496504 return this ;
497505} ;
498506
507+ /**
508+ * Register a `fn` to be fired when integrations are ready.
509+ *
510+ * If the first parameter is a function `fn`, `fn` is fired when all
511+ * integrations are ready.
512+ *
513+ * If the first parameter is a string `integration` and the second parameter is
514+ * a function `fn`, `fn` is fired when the given integration is ready.
515+ *
516+ * It is recommended that you use the latter, as the global ready callback may
517+ * not be fired if a single integration fails to load.
518+ * See https://github.com/segmentio/analytics.js/issues/409.
519+ *
520+ * @param {(Function|String) } a Callback function or integration name.
521+ * @param {Function } [b] Callback function.
522+ * @return {Analytics }
523+ */
524+
525+ Analytics . prototype . ready = function ( a , b ) {
526+ if ( is . fn ( a ) ) {
527+ return this . _ready ( a ) ;
528+ }
529+ return this . _integrationReady ( a , b ) ;
530+ } ;
531+
532+ /**
533+ * Register a `fn` to be fired when the given integration is ready.
534+ *
535+ * @param {String } [name] integration name.
536+ * @param {Function } [fn] Callback function.
537+ * @return {Analytics }
538+ */
539+
540+ Analytics . prototype . _integrationReady = function ( name , fn ) {
541+ if ( is . fn ( fn ) ) {
542+ if ( this . _readiedIntegrations [ name ] ) {
543+ nextTick ( fn ) ;
544+ } else {
545+ this . once ( name + '-ready' , fn ) ;
546+ }
547+ }
548+ return this ;
549+ } ;
550+
499551/**
500552 * Register a `fn` to be fired when all the analytics services are ready.
501553 *
502554 * @param {Function } fn
503555 * @return {Analytics }
504556 */
505557
506- Analytics . prototype . ready = function ( fn ) {
558+ Analytics . prototype . _ready = function ( fn ) {
507559 if ( is . fn ( fn ) ) {
508560 if ( this . _readied ) {
509561 nextTick ( fn ) ;
0 commit comments