Skip to content

Commit e0f6651

Browse files
authored
feat: reset retry mechanism on failure with next loader (#102)
1 parent 724beca commit e0f6651

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

src/index.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ test("script onerror should reject promise with multiple loaders", async () => {
139139
expect(loader["done"]).toBeTruthy();
140140
expect(loader["loading"]).toBeFalsy();
141141
expect(loader["onerrorEvent"]).toBeInstanceOf(ErrorEvent);
142+
142143
rejection = expect(extraLoader.load()).rejects.toBeInstanceOf(ErrorEvent);
144+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
143145

144146
await rejection;
145147
expect(extraLoader["done"]).toBeTruthy();
@@ -165,6 +167,52 @@ test("script onerror should retry", async () => {
165167
expect(console.log).toHaveBeenCalledTimes(loader.retries);
166168
});
167169

170+
test("script onerror should reset retry mechanism with next loader", async () => {
171+
const loader = new Loader({ apiKey: "foo", retries: 1 });
172+
const deleteScript = jest.spyOn(loader, "deleteScript");
173+
// eslint-disable-next-line @typescript-eslint/no-empty-function
174+
console.log = jest.fn();
175+
176+
let rejection = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent);
177+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
178+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
179+
jest.runAllTimers();
180+
await rejection;
181+
182+
rejection = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent);
183+
expect(loader["done"]).toBeFalsy();
184+
expect(loader["loading"]).toBeTruthy();
185+
expect(loader["errors"].length).toBe(0);
186+
187+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
188+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
189+
jest.runAllTimers();
190+
191+
await rejection;
192+
expect(deleteScript).toHaveBeenCalledTimes(3);
193+
expect(console.log).toHaveBeenCalledTimes(loader.retries * 2);
194+
});
195+
196+
test("script onerror should not reset retry mechanism with parallel loaders", async () => {
197+
const loader = new Loader({ apiKey: "foo", retries: 1 });
198+
const deleteScript = jest.spyOn(loader, "deleteScript");
199+
// eslint-disable-next-line @typescript-eslint/no-empty-function
200+
console.log = jest.fn();
201+
202+
const rejection1 = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent);
203+
const rejection2 = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent);
204+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
205+
loader["loadErrorCallback"](document.createEvent("ErrorEvent"));
206+
jest.runAllTimers();
207+
208+
await Promise.all([rejection1, rejection2]);
209+
expect(loader["done"]).toBeTruthy();
210+
expect(loader["loading"]).toBeFalsy();
211+
expect(loader["errors"].length).toBe(2);
212+
expect(deleteScript).toHaveBeenCalledTimes(1);
213+
expect(console.log).toHaveBeenCalledTimes(loader.retries);
214+
});
215+
168216
test("singleton should be used", () => {
169217
const loader = new Loader({ apiKey: "foo" });
170218
const extraLoader = new Loader({ apiKey: "foo" });

src/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,15 @@ export class Loader {
426426
}
427427
}
428428

429+
private resetIfRetryingFailed(): void {
430+
if (this.done && !this.loading && this.errors.length >= this.retries) {
431+
this.deleteScript();
432+
this.done = false;
433+
this.loading = false;
434+
this.errors = [];
435+
}
436+
}
437+
429438
private loadErrorCallback(e: ErrorEvent): void {
430439
this.errors.push(e);
431440

@@ -470,6 +479,7 @@ export class Loader {
470479
this.callback();
471480
}
472481

482+
this.resetIfRetryingFailed();
473483
if (this.done) {
474484
this.callback();
475485
} else {

0 commit comments

Comments
 (0)