diff --git a/CHANGELOG.md b/CHANGELOG.md index 22a85d79..e0acb48f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +#### v0.7.1 08.05.2017 + +* fixed bug in `Desktop.fetch` which when called multiple times with the same event, was serving the response only for the first call [#79](https://github.com/wojtkowiak/meteor-desktop/issues/79) + ## v0.7.0 04.05.2017 - added `--meteor-settings ` cmd option to pass `--settings ` to meteor when building with `-b` diff --git a/README.md b/README.md index 7038ae12..7c911521 100644 --- a/README.md +++ b/README.md @@ -423,7 +423,7 @@ Use it to call and listen for events from the desktop side. The only difference is that you always need to precede arguments with module name. There are two extra methods: -- **fetch** - like send but returns a `Promise` that resolves to a response +- **fetch```(module, event, timeout = 2000, ...args)```** - like send but returns a `Promise` that resolves to a response, timeouts after 2000ms by default - **sendGlobal** - alias for `ipcRenderer.send` - if you need to send an IPC that is not namespaced Example of `send` and `fetch` usage - [here](https://github.com/wojtkowiak/meteor-desktop-localstorage/blob/master/plugins/localstorage/localstorage.js#L9). diff --git a/skeleton/app.js b/skeleton/app.js index 15ca2677..7de4a393 100644 --- a/skeleton/app.js +++ b/skeleton/app.js @@ -568,7 +568,7 @@ class App { this.l.info('relaunching to use different version of desktop.asar'); // Give winston a chance to write the logs. setImmediate(() => { - app.relaunch({ args: process.argv.slice(1) + ['--hcp'] }); + app.relaunch({ args: process.argv.slice(1).concat('--hcp') }); app.exit(0); }); } else { diff --git a/skeleton/modules/module.js b/skeleton/modules/module.js index 63d99615..2ceba73a 100644 --- a/skeleton/modules/module.js +++ b/skeleton/modules/module.js @@ -47,7 +47,7 @@ export default class Module { * @public */ respond(event, fetchId, ...data) { - Module.sendInternal(this.getResponseEventName(event), fetchId, ...data); + Module.sendInternal(this.getResponseEventName(`${event}_${fetchId}`), fetchId, ...data); } /** diff --git a/skeleton/preload.js b/skeleton/preload.js index 41babf29..8e60fc42 100644 --- a/skeleton/preload.js +++ b/skeleton/preload.js @@ -1,8 +1,6 @@ // This was inspiried by // https://github.com/electron-webapps/meteor-electron/blob/master/app/preload.js - -const _ = require('lodash'); const ipc = require('electron').ipcRenderer; /** @@ -88,20 +86,22 @@ const Desktop = new (class { const eventName = response ? this.getResponseEventName(module, event) : this.getEventName(module, event); if (eventName in this[listeners]) { - this[listeners][eventName].push(callback); + this[listeners][eventName].add(callback); } else { - this[listeners][eventName] = [callback]; + this[listeners][eventName] = new Set([callback]); } if (!(eventName in this.registeredInIpc)) { this.registeredInIpc[eventName] = true; ipc.on(eventName, (...args) => { if (eventName in this.eventListeners) { - _.invokeMap(this.eventListeners[eventName], 'apply', undefined, args); + this.eventListeners[eventName].forEach(eventHandler => eventHandler(...args)); } if (eventName in this.onceEventListeners) { - _.invokeMap(this.onceEventListeners[eventName], 'apply', undefined, args); + this.onceEventListeners[eventName].forEach((eventHandler) => { + eventHandler(...args); + this.onceEventListeners[eventName].delete(eventHandler); + }); } - this.onceEventListeners[eventName] = []; }); } } @@ -160,8 +160,8 @@ const Desktop = new (class { */ removeAllListeners(module, event) { const eventName = this.getEventName(module, event); - this.onceEventListeners[eventName] = []; - this.eventListeners[eventName] = []; + this.onceEventListeners[eventName] = new Set(); + this.eventListeners[eventName] = new Set(); } /** @@ -197,8 +197,8 @@ const Desktop = new (class { const fetchId = this.fetchCallCounter; return new Promise((resolve, reject) => { - this.once(module, event, - (responsEvent, id, ...responseArgs) => { + this.once(module, `${event}_${fetchId}`, + (responseEvent, id, ...responseArgs) => { if (id === fetchId) { clearTimeout(this.fetchTimeoutTimers[fetchId]); delete this.fetchTimeoutTimers[fetchId]; diff --git a/tests/unit/skeleton/preload.test.js b/tests/unit/skeleton/preload.test.js index 828a610e..50edd14b 100644 --- a/tests/unit/skeleton/preload.test.js +++ b/tests/unit/skeleton/preload.test.js @@ -77,7 +77,7 @@ describe('Desktop', () => { try { expect(ipcMock.send).to.be.calledWith(`${module}__${event}`, 1, arg1, arg2); expect(desktop.onceEventListeners) - .to.have.a.property(`${module}__${event}___response`); + .to.have.a.property(`${module}__${event}_1___response`); revertIpc(); done(); } catch (e) { @@ -107,7 +107,7 @@ describe('Desktop', () => { expect(desktop[listeners]).to.have.a.property(`${module}__${event}`); callbacks.forEach((callback) => { - expect(desktop[listeners][`${module}__${event}`]).to.include(callback); + expect(desktop[listeners][`${module}__${event}`].has(callback)).to.be.true(); }); return { @@ -171,7 +171,7 @@ describe('Desktop', () => { expect(callback).to.be.calledOnce(); expect(callback).to.be.calledWith('desktop__event', arg1, arg2); - expect(test.desktop.onceEventListeners.desktop__event).to.be.empty(); + expect(test.desktop.onceEventListeners.desktop__event.size).to.equal(0); // Additionally we check if the ipc.on was triggered only once. expect(onSpy).to.be.calledOnce();