Skip to content

Commit cd2dbe5

Browse files
committed
Default eventbus to async
1 parent f067697 commit cd2dbe5

File tree

3 files changed

+61
-84
lines changed

3 files changed

+61
-84
lines changed

@types/services/pubsub/pubsub.d.ts

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class PubSubProvider {
1515
$get: () => PubSub;
1616
}
1717
export class PubSub {
18-
static $nonscope: any;
18+
static $nonscope: boolean;
1919
/**
2020
* Runs a function asynchronously.
2121
*
@@ -24,21 +24,7 @@ export class PubSub {
2424
* @param {Object} context Context in which to run the function.
2525
* @param {Array} args Arguments to pass to the function.
2626
*/
27-
private static runAsync_;
28-
/**
29-
* Topic-based publish/subscribe channel. Maintains a map of topics to
30-
* subscriptions. When a message is published to a topic, all functions
31-
* subscribed to that topic are invoked in the order they were added.
32-
* Uncaught errors abort publishing.
33-
*
34-
* Topics may be identified by any nonempty string, <strong>except</strong>
35-
* strings corresponding to native Object properties, e.g. "constructor",
36-
* "toString", "hasOwnProperty", etc.
37-
*
38-
* @param {boolean=} async Enable asynchronous behavior. Recommended for
39-
* new code. See notes on the publish() method.
40-
*/
41-
constructor(async?: boolean | undefined);
27+
private static runAsync;
4228
disposed: boolean;
4329
/**
4430
* The next available subscription key. Internally, this is an index into the
@@ -69,8 +55,9 @@ export class PubSub {
6955
* object at index (n + 2), the next topic at index (n + 3), etc. (This
7056
* representation minimizes the number of object allocations and has been
7157
* shown to be faster than an array of objects with three key-value pairs or
72-
* three parallel arrays, especially on IE.) Once a subscription is removed
73-
* via {@link unsubscribe} or {@link unsubscribeByKey}, the three
58+
* three parallel arrays, especially on IE.)
59+
*
60+
* Once a subscription is removed via {@link unsubscribe} or {@link unsubscribeByKey}, the three
7461
* corresponding array elements are deleted, and never reused. This means the
7562
* total number of subscriptions during the lifetime of the pubsub channel is
7663
* limited by the maximum length of a JavaScript array to (2^32 - 1) / 3 =
@@ -86,10 +73,6 @@ export class PubSub {
8673
* @private {!Object<!Array<number>>}
8774
*/
8875
private topics;
89-
/**
90-
* @private @const {boolean}
91-
*/
92-
private async_;
9376
/**
9477
* Subscribes a function to a topic. The function is invoked as a method on
9578
* the given `opt_context` object, or in the global scope if no context

src/services/pubsub/pubsub.js

Lines changed: 17 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class PubSubProvider {
1919
}
2020

2121
export class PubSub {
22-
static $nonscope;
22+
static $nonscope = true;
2323
/**
2424
* Topic-based publish/subscribe channel. Maintains a map of topics to
2525
* subscriptions. When a message is published to a topic, all functions
@@ -30,10 +30,8 @@ export class PubSub {
3030
* strings corresponding to native Object properties, e.g. "constructor",
3131
* "toString", "hasOwnProperty", etc.
3232
*
33-
* @param {boolean=} async Enable asynchronous behavior. Recommended for
34-
* new code. See notes on the publish() method.
3533
*/
36-
constructor(async = false) {
34+
constructor() {
3735
this.disposed = false;
3836

3937
/**
@@ -68,8 +66,9 @@ export class PubSub {
6866
* object at index (n + 2), the next topic at index (n + 3), etc. (This
6967
* representation minimizes the number of object allocations and has been
7068
* shown to be faster than an array of objects with three key-value pairs or
71-
* three parallel arrays, especially on IE.) Once a subscription is removed
72-
* via {@link unsubscribe} or {@link unsubscribeByKey}, the three
69+
* three parallel arrays, especially on IE.)
70+
*
71+
* Once a subscription is removed via {@link unsubscribe} or {@link unsubscribeByKey}, the three
7372
* corresponding array elements are deleted, and never reused. This means the
7473
* total number of subscriptions during the lifetime of the pubsub channel is
7574
* limited by the maximum length of a JavaScript array to (2^32 - 1) / 3 =
@@ -86,11 +85,6 @@ export class PubSub {
8685
* @private {!Object<!Array<number>>}
8786
*/
8887
this.topics = {};
89-
90-
/**
91-
* @private @const {boolean}
92-
*/
93-
this.async_ = Boolean(async);
9488
}
9589

9690
/**
@@ -176,7 +170,7 @@ export class PubSub {
176170
* @param {Object} context Context in which to run the function.
177171
* @param {Array} args Arguments to pass to the function.
178172
*/
179-
static runAsync_(fn, context, args) {
173+
static runAsync(fn, context, args) {
180174
queueMicrotask(() => {
181175
fn.apply(context, args);
182176
});
@@ -264,45 +258,16 @@ export class PubSub {
264258
if (keys) {
265259
const args = var_args;
266260

267-
if (this.async_) {
268-
// For each key in the list of subscription keys for the topic, schedule
269-
// the function to be applied to the arguments in the appropriate context.
270-
for (let i = 0; i < keys.length; i++) {
271-
const key = keys[i];
272-
273-
PubSub.runAsync_(
274-
this.subscriptions[key + 1],
275-
this.subscriptions[key + 2],
276-
args,
277-
);
278-
}
279-
} else {
280-
this.publishDepth++;
281-
282-
try {
283-
for (
284-
let i = 0, len = keys.length;
285-
i < len && !this.isDisposed();
286-
i++
287-
) {
288-
const key = keys[i];
289-
290-
this.subscriptions[key + 1].apply(
291-
this.subscriptions[key + 2],
292-
args,
293-
);
294-
}
295-
} finally {
296-
this.publishDepth--;
297-
298-
if (this.pendingKeys.length > 0 && this.publishDepth === 0) {
299-
let pendingKey;
300-
301-
while ((pendingKey = this.pendingKeys.pop())) {
302-
this.unsubscribeByKey(pendingKey);
303-
}
304-
}
305-
}
261+
// For each key in the list of subscription keys for the topic, schedule
262+
// the function to be applied to the arguments in the appropriate context.
263+
for (let i = 0, l = keys.length; i < l; i++) {
264+
const key = keys[i];
265+
266+
PubSub.runAsync(
267+
this.subscriptions[key + 1],
268+
this.subscriptions[key + 2],
269+
args,
270+
);
306271
}
307272

308273
return true;
@@ -362,4 +327,4 @@ export class PubSub {
362327
}
363328
}
364329

365-
export const EventBus = new PubSub(true);
330+
export const EventBus = new PubSub();

src/services/pubsub/pubsub.spec.js

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PubSub } from "./pubsub.js";
22
import { createInjector } from "../../core/di/injector.js";
33
import { Angular } from "../../angular.js";
4+
import { wait } from "../../shared/utils.js";
45

56
describe("PubSubProvider", () => {
67
it("should be injectable", () => {
@@ -9,7 +10,6 @@ describe("PubSubProvider", () => {
910
const $injector = createInjector(["test"]);
1011
expect($injector.has("$eventBus")).toBeTrue();
1112
expect($injector.get("$eventBus") instanceof PubSub).toBeTrue();
12-
expect($injector.get("$eventBus").async_).toBeTrue();
1313
});
1414
});
1515

@@ -117,18 +117,20 @@ describe("PubSub", function () {
117117
expect(pubsub.getCount("X")).toBe(0);
118118
});
119119

120-
it("should subscribe once correctly", function () {
120+
it("should subscribe once correctly", async function () {
121121
let called;
122122
let context;
123123

124124
called = false;
125125
pubsub.subscribeOnce("someTopic", () => {
126126
called = true;
127127
});
128+
await wait();
128129
expect(pubsub.getCount("someTopic")).toBe(1);
129130
expect(called).toBe(false);
130131

131132
pubsub.publish("someTopic");
133+
await wait();
132134
expect(pubsub.getCount("someTopic")).toBe(0);
133135
expect(called).toBe(true);
134136

@@ -140,10 +142,12 @@ describe("PubSub", function () {
140142
},
141143
context,
142144
);
145+
await wait();
143146
expect(pubsub.getCount("someTopic")).toBe(1);
144147
expect(context.called).toBe(false);
145148

146149
pubsub.publish("someTopic");
150+
await wait();
147151
expect(pubsub.getCount("someTopic")).toBe(0);
148152
expect(context.called).toBe(true);
149153

@@ -156,11 +160,13 @@ describe("PubSub", function () {
156160
},
157161
context,
158162
);
163+
await wait();
159164
expect(pubsub.getCount("someTopic")).toBe(1);
160165
expect(context.called).toBe(false);
161166
expect(context.value).toBe(0);
162167

163168
pubsub.publish("someTopic", 17);
169+
await wait();
164170
expect(pubsub.getCount("someTopic")).toBe(0);
165171
expect(context.called).toBe(true);
166172
expect(context.value).toBe(17);
@@ -227,7 +233,7 @@ describe("PubSub", function () {
227233
}, 0);
228234
});
229235

230-
it("should subscribe once with bound function correctly", function () {
236+
it("should subscribe once with bound function correctly", async function () {
231237
const context = { called: false, value: 0 };
232238

233239
function subscriber(value) {
@@ -236,17 +242,21 @@ describe("PubSub", function () {
236242
}
237243

238244
pubsub.subscribeOnce("someTopic", subscriber.bind(context));
245+
await wait();
246+
239247
expect(pubsub.getCount("someTopic")).toBe(1);
240248
expect(context.called).toBe(false);
241249
expect(context.value).toBe(0);
242250

243251
pubsub.publish("someTopic", 17);
252+
await wait();
253+
244254
expect(pubsub.getCount("someTopic")).toBe(0);
245255
expect(context.called).toBe(true);
246256
expect(context.value).toBe(17);
247257
});
248258

249-
it("should subscribe once with partial function correctly", function () {
259+
it("should subscribe once with partial function correctly", async function () {
250260
let called = false;
251261
let value = 0;
252262

@@ -256,17 +266,21 @@ describe("PubSub", function () {
256266
}
257267

258268
pubsub.subscribeOnce("someTopic", subscriber.bind(null, true));
269+
await wait();
270+
259271
expect(pubsub.getCount("someTopic")).toBe(1);
260272
expect(called).toBe(false);
261273
expect(value).toBe(0);
262274

263275
pubsub.publish("someTopic", 17);
276+
await wait();
277+
264278
expect(pubsub.getCount("someTopic")).toBe(0);
265279
expect(called).toBe(true);
266280
expect(value).toBe(17);
267281
});
268282

269-
it("should handle self resubscribe correctly", function () {
283+
it("should handle self resubscribe correctly", async function () {
270284
let value = null;
271285

272286
function resubscribe(iteration, newValue) {
@@ -275,18 +289,26 @@ describe("PubSub", function () {
275289
}
276290

277291
pubsub.subscribeOnce("someTopic", resubscribe.bind(null, 0));
292+
await wait();
293+
278294
expect(pubsub.getCount("someTopic")).toBe(1);
279295
expect(value).toBeNull();
280296

281297
pubsub.publish("someTopic", "foo");
298+
await wait();
299+
282300
expect(pubsub.getCount("someTopic")).toBe(1);
283301
expect(value).toBe("foo:0");
284302

285303
pubsub.publish("someTopic", "bar");
304+
await wait();
305+
286306
expect(pubsub.getCount("someTopic")).toBe(1);
287307
expect(value).toBe("bar:1");
288308

289309
pubsub.publish("someTopic", "baz");
310+
await wait();
311+
290312
expect(pubsub.getCount("someTopic")).toBe(1);
291313
expect(value).toBe("baz:2");
292314
});
@@ -352,50 +374,57 @@ describe("PubSub", function () {
352374
expect(record.y).toBe("y");
353375
}
354376

355-
it("should call subscribed functions on publish", function () {
377+
it("should call subscribed functions on publish", async function () {
356378
pubsub.subscribe(SOME_TOPIC, foo);
357379
pubsub.subscribe(SOME_TOPIC, bar, context);
358380

359381
expect(pubsub.publish(SOME_TOPIC, { x: "x", y: "y" })).toBe(true);
382+
await wait();
360383
expect(fooCalled).toBe(true, "foo() must have been called");
361384
expect(barCalled).toBe(true, "bar() must have been called");
362385
});
363386

364-
it("should not call unsubscribed functions on publish", function () {
387+
it("should not call unsubscribed functions on publish", async function () {
365388
pubsub.subscribe(SOME_TOPIC, foo);
366389
pubsub.subscribe(SOME_TOPIC, bar, context);
367390

368391
pubsub.publish(SOME_TOPIC, { x: "x", y: "y" });
392+
await wait();
393+
expect(fooCalled).toBe(true, "foo() must have been called");
394+
expect(barCalled).toBe(true, "bar() must have been called");
369395
fooCalled = false;
370396
barCalled = false;
371397
expect(pubsub.unsubscribe(SOME_TOPIC, foo)).toBe(true);
372-
373398
expect(pubsub.publish(SOME_TOPIC, { x: "x", y: "y" })).toBe(true);
399+
400+
await wait();
374401
expect(fooCalled).toBe(false, "foo() must not have been called");
375402
expect(barCalled).toBe(true, "bar() must have been called");
376403
});
377404

378-
it("should only call functions subscribed to the correct topic", function () {
405+
it("should only call functions subscribed to the correct topic", async function () {
379406
pubsub.subscribe(SOME_TOPIC, bar, context);
380407
pubsub.subscribe("differentTopic", foo);
381408

382409
pubsub.publish(SOME_TOPIC, { x: "x", y: "y" });
383410
fooCalled = false;
384411
barCalled = false;
385412

413+
await wait();
386414
expect(pubsub.publish(SOME_TOPIC, { x: "x", y: "y" })).toBe(true);
387415
expect(fooCalled).toBe(false, "foo() must not have been called");
388416
expect(barCalled).toBe(true, "bar() must have been called");
389417
});
390418

391-
it("should trigger functions if not arguments are provided", function () {
419+
it("should trigger functions if not arguments are provided", async function () {
392420
let called = false;
393421
pubsub.subscribe(SOME_TOPIC, () => {
394422
called = true;
395423
0;
396424
});
397425

398426
pubsub.publish(SOME_TOPIC);
427+
await wait();
399428

400429
expect(pubsub.publish(SOME_TOPIC)).toBe(true);
401430
expect(called).toBeTrue();

0 commit comments

Comments
 (0)