@@ -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,55 @@ 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+ * If the first parameter is a function `fn`, `fn` is firsted when all
510+ * integrations are ready.
511+ * If the first parameter is a name and the second parameter is a function `fn`,
512+ * `fn` is fired when the given integration is ready.
513+ *
514+ * It is recommended that you use the latter, as the global ready callback may
515+ * not be fired if a single integration fails to load.
516+ * See https://github.com/segmentio/analytics.js/issues/409.
517+ *
518+ * @param {(Function|String) } a
519+ * @param {Function } b
520+ * @return {Analytics }
521+ */
522+
523+ Analytics . prototype . ready = function ( a , b ) {
524+ if ( is . fn ( a ) ) {
525+ return this . _ready ( a ) ;
526+ }
527+ return this . _integrationReady ( a , b ) ;
528+ } ;
529+
530+ /**
531+ * Register a `fn` to be fired when the given analytics service is ready.
532+ *
533+ * @param {Function } fn
534+ * @return {Analytics }
535+ */
536+
537+ Analytics . prototype . _integrationReady = function ( name , fn ) {
538+ if ( is . fn ( fn ) ) {
539+ if ( this . _readiedIntegrations [ name ] ) {
540+ nextTick ( fn ) ;
541+ } else {
542+ this . once ( name + '-ready' , fn ) ;
543+ }
544+ }
545+ return this ;
546+ } ;
547+
499548/**
500549 * Register a `fn` to be fired when all the analytics services are ready.
501550 *
502551 * @param {Function } fn
503552 * @return {Analytics }
504553 */
505554
506- Analytics . prototype . ready = function ( fn ) {
555+ Analytics . prototype . _ready = function ( fn ) {
507556 if ( is . fn ( fn ) ) {
508557 if ( this . _readied ) {
509558 nextTick ( fn ) ;
0 commit comments