Skip to content

Commit e814e09

Browse files
committed
Added support for callback functions
1 parent f925b10 commit e814e09

File tree

6 files changed

+284
-26
lines changed

6 files changed

+284
-26
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Unreleased
22

3+
* Add support for passing callback functions to logEvent
4+
5+
## 2.3.0 (September 2, 2015)
6+
37
* Add option to batch events into a single request.
48

59
## 2.2.1 (Aug 13, 2015)

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,20 @@ User IDs are automatically generated and stored in cookies if not specified.
118118
Device IDs are generated randomly, although you can define a custom device ID setting it as a configuration option or by calling:
119119

120120
amplitude.setDeviceId("CUSTOM_DEVICE_ID");
121+
122+
You can pass a callback function to logEvent, which will get called after receiving a response from the server:
123+
124+
amplitude.logEvent("EVENT_IDENTIFIER_HERE", null, callback_function);
125+
126+
The status and response from the server are passed to the callback function, which you might find useful. An example of a callback function which redirects the browser to another site after a response:
127+
128+
'''javascript
129+
var callback_function = function(status, response) {
130+
if (status === 200 && response === 'success') {
131+
// do something here
132+
}
133+
window.location.replace('URL_OF_OTHER_SITE');
134+
};
135+
'''
136+
137+
In the case that `optOut` is true, then no event will be logged, but the callback will be run. In the case that `batchEvents` is true, if the batch requirements `eventUploadThreshold` and `eventUploadPeriodMillis` are not met when `logEvent` is called, then no request is sent, but the callback is still called.

amplitude.js

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -262,21 +262,24 @@ Amplitude.prototype.nextEventId = function() {
262262
return this._eventId;
263263
};
264264

265-
Amplitude.prototype._sendEventsIfReady = function() {
265+
// returns true if sendEvents called
266+
Amplitude.prototype._sendEventsIfReady = function(callback) {
266267
if (this._unsentEvents.length === 0) {
267-
return;
268+
return false;
268269
}
269270

270271
if (!this.options.batchEvents) {
271-
this.sendEvents();
272-
return;
272+
this.sendEvents(callback);
273+
return true;
273274
}
274275

275276
if (this._unsentEvents.length >= this.options.eventUploadThreshold) {
276-
this.sendEvents();
277-
} else {
278-
setTimeout(this.sendEvents.bind(this), this.options.eventUploadPeriodMillis);
277+
this.sendEvents(callback);
278+
return true;
279279
}
280+
281+
setTimeout(this.sendEvents.bind(this), this.options.eventUploadPeriodMillis);
282+
return false;
280283
};
281284

282285
var _loadCookieData = function(scope) {
@@ -431,8 +434,15 @@ Amplitude.prototype.setVersionName = function(versionName) {
431434
/**
432435
* Private logEvent method. Keeps apiProperties from being publicly exposed.
433436
*/
434-
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties) {
437+
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties, callback) {
438+
if (typeof callback !== 'function') {
439+
callback = null;
440+
}
441+
435442
if (!eventType || this.options.optOut) {
443+
if (callback) {
444+
callback(0, 'No request sent');
445+
}
436446
return;
437447
}
438448
try {
@@ -501,7 +511,9 @@ Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperti
501511
this.saveEvents();
502512
}
503513

504-
this._sendEventsIfReady();
514+
if (!this._sendEventsIfReady(callback) && callback) {
515+
callback(0, 'No request sent');
516+
}
505517

506518
return eventId;
507519
} catch (e) {
@@ -513,6 +525,10 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
513525
return this._logEvent(eventType, eventProperties);
514526
};
515527

528+
Amplitude.prototype.logEvent = function(eventType, eventProperties, callback) {
529+
return this._logEvent(eventType, eventProperties, null, callback);
530+
};
531+
516532
// Test that n is a number or a numeric value.
517533
var _isNumber = function(n) {
518534
return !isNaN(parseFloat(n)) && isFinite(n);
@@ -547,7 +563,7 @@ Amplitude.prototype.removeEvents = function (maxEventId) {
547563
this._unsentEvents = filteredEvents;
548564
};
549565

550-
Amplitude.prototype.sendEvents = function() {
566+
Amplitude.prototype.sendEvents = function(callback) {
551567
if (!this._sending && !this.options.optOut && this._unsentEvents.length > 0) {
552568
this._sending = true;
553569
var url = ('https:' === window.location.protocol ? 'https' : 'http') + '://' +
@@ -581,7 +597,9 @@ Amplitude.prototype.sendEvents = function() {
581597
}
582598

583599
// Send more events if any queued during previous send.
584-
scope._sendEventsIfReady();
600+
if (!scope._sendEventsIfReady(callback) && callback) {
601+
callback(status, response);
602+
}
585603

586604
} else if (status === 413) {
587605
//log('request too large');
@@ -593,12 +611,17 @@ Amplitude.prototype.sendEvents = function() {
593611
// The server complained about the length of the request.
594612
// Backoff and try again.
595613
scope.options.uploadBatchSize = Math.ceil(numEvents / 2);
596-
scope.sendEvents();
614+
scope.sendEvents(callback);
615+
616+
} else if (callback) { // If server turns something like a 400
617+
callback(status, response);
597618
}
598619
} catch (e) {
599620
//log('failed upload');
600621
}
601622
});
623+
} else if (callback) {
624+
callback(0, 'No request sent');
602625
}
603626
};
604627

amplitude.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/amplitude.js

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,21 +150,24 @@ Amplitude.prototype.nextEventId = function() {
150150
return this._eventId;
151151
};
152152

153-
Amplitude.prototype._sendEventsIfReady = function() {
153+
// returns true if sendEvents called
154+
Amplitude.prototype._sendEventsIfReady = function(callback) {
154155
if (this._unsentEvents.length === 0) {
155-
return;
156+
return false;
156157
}
157158

158159
if (!this.options.batchEvents) {
159-
this.sendEvents();
160-
return;
160+
this.sendEvents(callback);
161+
return true;
161162
}
162163

163164
if (this._unsentEvents.length >= this.options.eventUploadThreshold) {
164-
this.sendEvents();
165-
} else {
166-
setTimeout(this.sendEvents.bind(this), this.options.eventUploadPeriodMillis);
165+
this.sendEvents(callback);
166+
return true;
167167
}
168+
169+
setTimeout(this.sendEvents.bind(this), this.options.eventUploadPeriodMillis);
170+
return false;
168171
};
169172

170173
var _loadCookieData = function(scope) {
@@ -319,8 +322,15 @@ Amplitude.prototype.setVersionName = function(versionName) {
319322
/**
320323
* Private logEvent method. Keeps apiProperties from being publicly exposed.
321324
*/
322-
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties) {
325+
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties, callback) {
326+
if (typeof callback !== 'function') {
327+
callback = null;
328+
}
329+
323330
if (!eventType || this.options.optOut) {
331+
if (callback) {
332+
callback(0, 'No request sent');
333+
}
324334
return;
325335
}
326336
try {
@@ -389,7 +399,9 @@ Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperti
389399
this.saveEvents();
390400
}
391401

392-
this._sendEventsIfReady();
402+
if (!this._sendEventsIfReady(callback) && callback) {
403+
callback(0, 'No request sent');
404+
}
393405

394406
return eventId;
395407
} catch (e) {
@@ -401,6 +413,10 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
401413
return this._logEvent(eventType, eventProperties);
402414
};
403415

416+
Amplitude.prototype.logEvent = function(eventType, eventProperties, callback) {
417+
return this._logEvent(eventType, eventProperties, null, callback);
418+
};
419+
404420
// Test that n is a number or a numeric value.
405421
var _isNumber = function(n) {
406422
return !isNaN(parseFloat(n)) && isFinite(n);
@@ -435,7 +451,7 @@ Amplitude.prototype.removeEvents = function (maxEventId) {
435451
this._unsentEvents = filteredEvents;
436452
};
437453

438-
Amplitude.prototype.sendEvents = function() {
454+
Amplitude.prototype.sendEvents = function(callback) {
439455
if (!this._sending && !this.options.optOut && this._unsentEvents.length > 0) {
440456
this._sending = true;
441457
var url = ('https:' === window.location.protocol ? 'https' : 'http') + '://' +
@@ -469,7 +485,9 @@ Amplitude.prototype.sendEvents = function() {
469485
}
470486

471487
// Send more events if any queued during previous send.
472-
scope._sendEventsIfReady();
488+
if (!scope._sendEventsIfReady(callback) && callback) {
489+
callback(status, response);
490+
}
473491

474492
} else if (status === 413) {
475493
//log('request too large');
@@ -481,12 +499,17 @@ Amplitude.prototype.sendEvents = function() {
481499
// The server complained about the length of the request.
482500
// Backoff and try again.
483501
scope.options.uploadBatchSize = Math.ceil(numEvents / 2);
484-
scope.sendEvents();
502+
scope.sendEvents(callback);
503+
504+
} else if (callback) { // If server turns something like a 400
505+
callback(status, response);
485506
}
486507
} catch (e) {
487508
//log('failed upload');
488509
}
489510
});
511+
} else if (callback) {
512+
callback(0, 'No request sent');
490513
}
491514
};
492515

0 commit comments

Comments
 (0)