Skip to content

Commit e69f8b3

Browse files
committed
Update listen/unlisten code for merge
1 parent 360b896 commit e69f8b3

File tree

4 files changed

+138
-173
lines changed

4 files changed

+138
-173
lines changed

README.md

+27-27
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ Features an API using ES6 promises.
1717
* [CrossStorageClient.prototype.del(key1, \[key2\], \[...\])](#crossstorageclientprototypedelkey1-key2-)
1818
* [CrossStorageClient.prototype.getKeys()](#crossstorageclientprototypegetkeys)
1919
* [CrossStorageClient.prototype.clear()](#crossstorageclientprototypeclear)
20-
* [CrossStorageClient.prototype.close()](#crossstorageclientprototypeclose)
2120
* [CrossStorageClient.prototype.listen(callback)](#crossstorageclientprototypelisten)
2221
* [CrossStorageClient.prototype.unlisten(key)](#crossstorageclientprototypeunlisten)
22+
* [CrossStorageClient.prototype.close()](#crossstorageclientprototypeclose)
2323
* [Compatibility](#compatibility)
2424
* [Compression](#compression)
2525
* [Building](#building)
@@ -233,47 +233,47 @@ storage.onConnect().then(function() {
233233
});
234234
```
235235

236-
#### CrossStorageClient.prototype.close()
236+
#### CrossStorageClient.prototype.listen(fn)
237237

238-
Deletes the iframe and sets the connected state to false. The client can
239-
no longer be used after being invoked.
238+
Adds an event listener to the storage event in the hub. The callback will
239+
be invoked on any storage event not originating from that client. The
240+
callback will be invoked with an object containing the following keys taken
241+
from the original event: `key`, `newValue`, `oldValue` and `url`. Returns a
242+
promise that resolves to a listener id that can be used to unregister the
243+
listener.
240244

241245
``` javascript
242246
storage.onConnect().then(function() {
243-
return storage.set('key1', 'key2');
244-
}).catch(function(err) {
245-
// Handle error
246-
}).then(function() {
247-
storage.close();
247+
return storage.listen(function(event) {
248+
console.log(event);
249+
});
250+
}).then(function(id) {
251+
// id can be passed to storage.unlisten
248252
});
249253
```
250254

251-
#### CrossStorageClient.prototype.listen(callback)
252-
253-
Adds an event listener to the `storage` event in the hub. All `storage` events
254-
will be sent to the client and used to call the given callback.
255+
#### CrossStorageClient.prototype.unlisten(id)
255256

256-
The callback will be called on each `storage` event, with an object with the
257-
keys `key`, `newValue`, `oldValue` and `url` taken from the original event.
257+
Removes the registered listener with the supplied id. Returns a promise
258+
that resolves on completion.
258259

259260
``` javascript
260-
var storageEventListenerKey;
261-
storage.onConnect().then(function() {
262-
return storage.listen(console.log);
263-
}).then(function(key) {
264-
storageEventListenerKey = key
265-
});
261+
storage.unlisten(id);
266262
```
267263

268-
#### CrossStorageClient.prototype.unlisten(eventKey)
264+
#### CrossStorageClient.prototype.close()
269265

270-
Removes the storage event listener.
271-
272-
The client will ignore any events as soon as this is called. Returns a promise
273-
that is settled on successful event listener removal from the hub.
266+
Deletes the iframe and sets the connected state to false. The client can
267+
no longer be used after being invoked.
274268

275269
``` javascript
276-
storage.unlisten(storageEventListenerKey);
270+
storage.onConnect().then(function() {
271+
return storage.set('key1', 'key2');
272+
}).catch(function(err) {
273+
// Handle error
274+
}).then(function() {
275+
storage.close();
276+
});
277277
```
278278

279279
## Compatibility

lib/client.js

+39-43
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@
4848
this._count = 0;
4949
this._timeout = opts.timeout || 5000;
5050
this._listener = null;
51-
this._storageEventListeners = {};
52-
this._storageEventListenerCount = 0;
51+
52+
this._storageListeners = {};
53+
this._storageListenerCount = 0;
5354

5455
this._installListener();
5556

@@ -195,44 +196,6 @@
195196
return this._request('get', {keys: args});
196197
};
197198

198-
/**
199-
* Accepts a callback which will be called on `storage` events from the hub.
200-
*
201-
* The callback will be called on changes to the hub's storage (trigger from
202-
* other documents than the hub). It will be called with an object with
203-
* the keys `key`, `newValue`, `oldValue` and `url`, as defined by the `storage`
204-
* event in the hub.
205-
*
206-
* Returns a promise that is settled on success (in adding the event listener),
207-
* in which case it is fullfilled with a key that can be used to remove the
208-
* listener. On failure, it is rejected with the corresponding error message.
209-
*
210-
* @param {function} callback Function to be called on storage changes
211-
* @returns {Promise} A promise that is settled on hub response or timeout
212-
*/
213-
CrossStorageClient.prototype.listen = function(callback) {
214-
this._storageEventListenerCount++;
215-
var eventKey = this._id + ":" + this._storageEventListenerCount;
216-
this._storageEventListeners[eventKey] = callback;
217-
return this._request('listen', {eventKey: eventKey}).then(function () {
218-
return eventKey
219-
});
220-
};
221-
222-
/**
223-
* Removes the storage event listener.
224-
*
225-
* The client will ignore any events as soon as this is called. Returns a promise
226-
* that is settled on successful event listener removal from the hub.
227-
*
228-
* @param {string} eventKey The key returned initiating the listener with `listen`
229-
* @returns {Promise} A promise that is settled on hub response or timeout
230-
*/
231-
CrossStorageClient.prototype.unlisten = function(eventKey) {
232-
delete this._storageEventListeners[eventKey];
233-
return this._request('unlisten', {eventKey: eventKey});
234-
};
235-
236199
/**
237200
* Accepts one or more keys for deletion. Returns a promise that is settled on
238201
* hub response or timeout.
@@ -266,6 +229,39 @@
266229
return this._request('getKeys');
267230
};
268231

232+
/**
233+
* Adds an event listener to the storage event in the hub. The callback will
234+
* be invoked on any storage event not originating from that client. The
235+
* callback will be invoked with an object containing the following keys taken
236+
* from the original event: `key`, `newValue`, `oldValue` and `url`. Returns a
237+
* promise that resolves to a listener id that can be used to unregister the
238+
* listener.
239+
*
240+
* @param {function} fn Callback to invoke on storage event
241+
* @returns {Promise} A promise that is settled on hub response or timeout
242+
*/
243+
CrossStorageClient.prototype.listen = function(fn) {
244+
this._storageListenerCount++;
245+
var id = this._id + ":" + this._storageListenerCount;
246+
this._storageListeners[id] = fn;
247+
return this._request('listen', {listenerId: id}).then(function() {
248+
return id;
249+
});
250+
};
251+
252+
/**
253+
* Removes the registered listener with the supplied id. Returns a promise
254+
* that resolves on completion.
255+
*
256+
* @param {string} id The id of the listener to unregister
257+
* @returns {Promise} A promise that is settled on hub response or timeout
258+
*/
259+
CrossStorageClient.prototype.unlisten = function(id) {
260+
delete this._storageListeners[id];
261+
return this._request('unlisten', {listenerId: id});
262+
};
263+
264+
269265
/**
270266
* Deletes the iframe and sets the connected state to false. The client can
271267
* no longer be used after being invoked.
@@ -347,9 +343,9 @@
347343
return;
348344
}
349345

350-
if(response.type === 'event') {
351-
if (response.eventKey in client._storageEventListeners) {
352-
client._storageEventListeners[response.eventKey](response.eventData);
346+
if (response.event) {
347+
if (client._storageListeners[response.listenerId]) {
348+
client._storageListeners[response.listenerId](response.event);
353349
}
354350
return;
355351
}

lib/hub.js

+25-20
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
}
3939

4040
CrossStorageHub._permissions = permissions || [];
41-
CrossStorageHub._eventListeners = {};
41+
CrossStorageHub._storageListeners = {};
4242
CrossStorageHub._installListener();
4343
window.parent.postMessage('cross-storage:ready', '*');
4444
};
@@ -121,16 +121,21 @@
121121
/**
122122
* Returns a boolean indicating whether or not the requested method is
123123
* permitted for the given origin. The argument passed to method is expected
124-
* to be one of 'get', 'set', 'del', 'clear', 'listen' or 'getKeys'.
124+
* to be one of 'get', 'set', 'del', 'clear', 'getKeys', 'listen', or
125+
* 'unlisten'.
125126
*
126127
* @param {string} origin The origin for which to determine permissions
127128
* @param {string} method Requested action
128129
* @returns {bool} Whether or not the request is permitted
129130
*/
130131
CrossStorageHub._permitted = function(origin, method) {
131132
var available, i, entry, match;
132-
if (method==='unlisten') method = 'listen';
133-
available = ['get', 'set', 'listen', 'del', 'clear', 'getKeys'];
133+
available = ['get', 'set', 'listen', 'del', 'clear', 'getKeys', 'listen'];
134+
135+
if (method === 'unlisten') {
136+
method = 'listen';
137+
}
138+
134139
if (!CrossStorageHub._inArray(method, available)) {
135140
return false;
136141
}
@@ -187,54 +192,54 @@
187192
};
188193

189194
/**
190-
* Adds an event listener to `storage` events which sends all events to the client with the given eventKey
195+
* Listens to storage events, sending them to the client.
191196
*
192-
* @param {object} params An object with an eventKey
197+
* @param {object} params An object with a listener id
193198
*/
194199
CrossStorageHub._listen = function(params) {
195-
if (params.eventKey in CrossStorageHub._eventListeners) {
196-
throw new Error("Can't reuse eventKeys")
200+
if (params.listenerId in CrossStorageHub._storageListeners) {
201+
return;
197202
}
203+
198204
var handler = function(event) {
199-
if (event.storageArea != window.localStorage) return;
205+
if (event.storageArea !== window.localStorage) return;
206+
200207
var data = {
201-
type: 'event',
202-
eventKey: params.eventKey,
203-
eventData: {
208+
listenerId: params.listenerId,
209+
event: {
204210
key: event.key,
205211
newValue: event.newValue,
206212
oldValue: event.oldValue,
207213
url: event.url
208-
// storageArea, ignored because we only use localStorage
209214
}
210215
};
216+
211217
window.parent.postMessage(JSON.stringify(data), '*');
212218
};
213219

214-
// Support IE8 with attachEvent
220+
CrossStorageHub._storageListeners[params.listenerId] = handler;
221+
215222
if (window.addEventListener) {
216223
window.addEventListener('storage', handler, false);
217224
} else {
218225
window.attachEvent('onstorage', handler);
219226
}
220-
CrossStorageHub._eventListeners[params.eventKey] = handler
221227
};
222228

223229
/**
224-
* Removes an event listener with the given eventKey
230+
* Removes an event listener with the given id
225231
*
226-
* @param {object} params An object with an eventKey
232+
* @param {object} params An object with an id
227233
*/
228234
CrossStorageHub._unlisten = function(params) {
229-
var handler = CrossStorageHub._eventListeners[params.eventKey];
235+
var handler = CrossStorageHub._storageListeners[params.listenerId];
236+
CrossStorageHub._storageListeners[params.listenerId] = null;
230237

231-
// Support IE8 with attachEvent
232238
if (window.removeEventListener) {
233239
window.removeEventListener('storage', handler, false);
234240
} else {
235241
window.detachEvent('onstorage', handler);
236242
}
237-
CrossStorageHub._eventListeners[params.eventKey] = null
238243
};
239244

240245
/**

0 commit comments

Comments
 (0)