Merge pull request #2273 from RationAI/master

EventSource: promises, priorities and execution breaks
This commit is contained in:
Ian Gilman 2023-01-24 14:53:07 -08:00 committed by GitHub
commit d22eceed66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 118 additions and 24 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "openseadragon", "name": "openseadragon",
"version": "3.1.0", "version": "4.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "openseadragon", "name": "openseadragon",
"version": "3.1.0", "version": "4.0.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"devDependencies": { "devDependencies": {
"grunt": "^1.4.1", "grunt": "^1.4.1",

View File

@ -58,7 +58,7 @@ $.EventSource.prototype = {
/** /**
* Add an event handler to be triggered only once (or a given number of times) * Add an event handler to be triggered only once (or a given number of times)
* for a given event. * for a given event. It is not removable with removeHandler().
* @function * @function
* @param {String} eventName - Name of event to register. * @param {String} eventName - Name of event to register.
* @param {OpenSeadragon.EventHandler} handler - Function to call when event * @param {OpenSeadragon.EventHandler} handler - Function to call when event
@ -67,8 +67,9 @@ $.EventSource.prototype = {
* to the handler. * to the handler.
* @param {Number} [times=1] - The number of times to handle the event * @param {Number} [times=1] - The number of times to handle the event
* before removing it. * before removing it.
* @param {Number} [priority=0] - Handler priority. By default, all priorities are 0. Higher number = priority.
*/ */
addOnceHandler: function(eventName, handler, userData, times) { addOnceHandler: function(eventName, handler, userData, times, priority) {
var self = this; var self = this;
times = times || 1; times = times || 1;
var count = 0; var count = 0;
@ -77,9 +78,9 @@ $.EventSource.prototype = {
if (count === times) { if (count === times) {
self.removeHandler(eventName, onceHandler); self.removeHandler(eventName, onceHandler);
} }
handler(event); return handler(event);
}; };
this.addHandler(eventName, onceHandler, userData); this.addHandler(eventName, onceHandler, userData, priority);
}, },
/** /**
@ -88,14 +89,22 @@ $.EventSource.prototype = {
* @param {String} eventName - Name of event to register. * @param {String} eventName - Name of event to register.
* @param {OpenSeadragon.EventHandler} handler - Function to call when event is triggered. * @param {OpenSeadragon.EventHandler} handler - Function to call when event is triggered.
* @param {Object} [userData=null] - Arbitrary object to be passed unchanged to the handler. * @param {Object} [userData=null] - Arbitrary object to be passed unchanged to the handler.
* @param {Number} [priority=0] - Handler priority. By default, all priorities are 0. Higher number = priority.
*/ */
addHandler: function ( eventName, handler, userData ) { addHandler: function ( eventName, handler, userData, priority ) {
var events = this.events[ eventName ]; var events = this.events[ eventName ];
if ( !events ) { if ( !events ) {
this.events[ eventName ] = events = []; this.events[ eventName ] = events = [];
} }
if ( handler && $.isFunction( handler ) ) { if ( handler && $.isFunction( handler ) ) {
events[ events.length ] = { handler: handler, userData: userData || null }; var index = events.length,
event = { handler: handler, userData: userData || null, priority: priority || 0 };
events[ index ] = event;
while ( index > 0 && events[ index - 1 ].priority < events[ index ].priority ) {
events[ index ] = events[ index - 1 ];
events[ index - 1 ] = event;
index--;
}
} }
}, },
@ -156,7 +165,7 @@ $.EventSource.prototype = {
* @function * @function
* @param {String} eventName - Name of event to get handlers for. * @param {String} eventName - Name of event to get handlers for.
*/ */
getHandler: function ( eventName ) { getHandler: function ( eventName) {
var events = this.events[ eventName ]; var events = this.events[ eventName ];
if ( !events || !events.length ) { if ( !events || !events.length ) {
return null; return null;
@ -186,15 +195,12 @@ $.EventSource.prototype = {
raiseEvent: function( eventName, eventArgs ) { raiseEvent: function( eventName, eventArgs ) {
//uncomment if you want to get a log of all events //uncomment if you want to get a log of all events
//$.console.log( eventName ); //$.console.log( eventName );
var handler = this.getHandler( eventName ); var handler = this.getHandler( eventName );
if ( handler ) { if ( handler ) {
if ( !eventArgs ) { return handler( this, eventArgs || {} );
eventArgs = {};
}
handler( this, eventArgs );
} }
return undefined;
} }
}; };

View File

@ -830,6 +830,8 @@ function OpenSeadragon( options ){
'[object Number]': 'number', '[object Number]': 'number',
'[object String]': 'string', '[object String]': 'string',
'[object Function]': 'function', '[object Function]': 'function',
'[object AsyncFunction]': 'function',
'[object Promise]': 'promise',
'[object Array]': 'array', '[object Array]': 'array',
'[object Date]': 'date', '[object Date]': 'date',
'[object RegExp]': 'regexp', '[object RegExp]': 'regexp',
@ -849,7 +851,6 @@ function OpenSeadragon( options ){
return $.type(obj) === "function"; return $.type(obj) === "function";
}; };
/** /**
* Taken from jQuery 1.6.1 * Taken from jQuery 1.6.1
* @function isArray * @function isArray

View File

@ -65,6 +65,7 @@
<!-- Polyfill must be inserted first because it is testing functions <!-- Polyfill must be inserted first because it is testing functions
reassignments which could be done by other test. --> reassignments which could be done by other test. -->
<script src="/test/modules/polyfills.js"></script> <script src="/test/modules/polyfills.js"></script>
<script src="/test/modules/event-source.js"></script>
<script src="/test/modules/basic.js"></script> <script src="/test/modules/basic.js"></script>
<script src="/test/modules/strings.js"></script> <script src="/test/modules/strings.js"></script>
<script src="/test/modules/formats.js"></script> <script src="/test/modules/formats.js"></script>

View File

@ -0,0 +1,85 @@
/* global QUnit, $, TouchUtil, Util, testLog */
(function () {
var context, result=[], eName = "test", eventCounter = 0, finished = false;
function evaluateTest(e) {
if (finished) return;
finished = true;
e.assert.strictEqual(JSON.stringify(result), JSON.stringify(e.expected), e.message);
e.done();
}
function executor(i, ms) {
if (ms === undefined) return function (e) {
eventCounter++;
result.push(i);
if (eventCounter === context.numberOfHandlers(eName)) {
evaluateTest(e);
}
};
return function (e) {
return new Promise(function (resolve) {
setTimeout(function () {
eventCounter++;
result.push(i);
if (eventCounter === context.numberOfHandlers(eName)) {
evaluateTest(e);
}
resolve();
}, ms);
});
}
}
function runTest(e) {
context.raiseEvent(eName, e);
}
QUnit.module( 'EventSource', {
beforeEach: function () {
context = new OpenSeadragon.EventSource();
eventCounter = 0;
result = [];
finished = false;
}
} );
// ----------
QUnit.test('EventSource: no events', function(assert) {
context.addHandler(eName, evaluateTest);
runTest({
assert: assert,
done: assert.async(),
expected: [],
message: 'No handlers registered - arrays should be empty.'
});
});
QUnit.test('EventSource: simple callbacks order', function(assert) {
context.addHandler(eName, executor(1));
context.addHandler(eName, executor(2));
context.addHandler(eName, executor(3));
runTest({
assert: assert,
done: assert.async(),
expected: [1, 2, 3],
message: 'Simple callback order should follow [1,2,3].'
});
});
QUnit.test('EventSource: priority callbacks order', function(assert) {
context.addHandler(eName, executor(1), undefined, 20);
context.addHandler(eName, executor(2), undefined, 124);
context.addHandler(eName, executor(3), undefined, -5);
context.addHandler(eName, executor(4));
context.addHandler(eName, executor(5), undefined, -2);
runTest({
assert: assert,
done: assert.async(),
expected: [2, 1, 4, 5, 3],
message: 'Prioritized callback order should follow [2,1,4,5,3].'
});
});
} )();

View File

@ -22,6 +22,7 @@
<!-- Polyfill must be inserted first because it is testing functions <!-- Polyfill must be inserted first because it is testing functions
reassignments which could be done by other test. --> reassignments which could be done by other test. -->
<script src="/test/modules/polyfills.js"></script> <script src="/test/modules/polyfills.js"></script>
<script src="/test/modules/event-source.js"></script>
<script src="/test/modules/viewerretrieval.js"></script> <script src="/test/modules/viewerretrieval.js"></script>
<script src="/test/modules/basic.js"></script> <script src="/test/modules/basic.js"></script>
<script src="/test/modules/strings.js"></script> <script src="/test/modules/strings.js"></script>