diff --git a/lib/Fetch.js b/lib/Fetch.js index 7902e53..c8db307 100644 --- a/lib/Fetch.js +++ b/lib/Fetch.js @@ -2,22 +2,32 @@ module.exports = class Fetch { constructor(browserFetch) { - const stack = []; + const stack = new Map(); function fetch(...args) { + const key = args; const request = browserFetch(...args); - const stackedProm = request.then(() => { - stack.pop(); - }).catch(() => { - stack.pop(); - }); - stack.push(stackedProm); + const stackedProm = request + .then(() => { + stack.delete(key); + return [ null ].concat(args); + }) + .catch((error) => { + stack.delete(key); + return [ error ].concat(args); + }); + + stack.set(key, stackedProm); return request; } - fetch._pendingRequests = stack; + Object.defineProperty(fetch, "_pendingRequests", { + get() { + return Array.from(stack.values()); + }, + }); return fetch; } diff --git a/test/fetch-test.js b/test/fetch-test.js index b6ab7e5..2929af6 100644 --- a/test/fetch-test.js +++ b/test/fetch-test.js @@ -304,17 +304,61 @@ describe("window.fetch", () => { }); it("exposes pendingRequests promise list", async () => { + let resolveFastRequest; + const pendingFastResponse = new Promise((resolve) => { + resolveFastRequest = resolve; + }); + let resolveSlowRequest; + const pendingSlowResponse = new Promise((resolve) => { + resolveSlowRequest = resolve; + }); + nock("https://blahonga.expressen.se") + .get("/fast-request") + .reply(async () => { + await pendingFastResponse; + return [ 200 ]; + }) + .get("/slow-request") + .reply(async () => { + await pendingSlowResponse; + return [ 200 ]; + }); + const browser = await new Browser(app).navigateTo("/"); + expect(browser.window.fetch._pendingRequests.length).to.equal(0); + + browser.window.fetch("https://blahonga.expressen.se/fast-request"); + browser.window.fetch("https://blahonga.expressen.se/slow-request", { priority: "low" }); + browser.window.fetch("https://blahonga.expressen.se/error-request"); + + const pendingRequests = browser.window.fetch._pendingRequests; + expect(pendingRequests.length).to.equal(3); + + const done = []; + const pendingAllDone = Promise.all(pendingRequests) + .then(() => done.push("all")); + const results = []; + for (const pendingRequest of pendingRequests) { + pendingRequest + .then((r) => results.push(r)); + } + + resolveFastRequest(); + await pendingRequests[0]; - let completed = 0; - browser.window.fetch("/req?q=1").then(() => ++completed); - browser.window.fetch("/req?q=2").then(() => ++completed); + Promise.all(browser.window.fetch._pendingRequests) + .then(() => done.push("all, mid process")); - expect(browser.window.fetch._pendingRequests).to.have.length(2); + resolveSlowRequest(); + await pendingAllDone; - await Promise.all(browser.window.fetch._pendingRequests); + expect(done).to.deep.equal([ "all", "all, mid process" ]); - expect(completed).to.equal(2); + expect(results[0]).to.include.members([ "https://blahonga.expressen.se/error-request" ]); + expect(results[0][0]).to.be.an.instanceof(Error); + expect(results[1]).to.deep.equal([ null, "https://blahonga.expressen.se/fast-request" ]); + expect(results[2]).to.include.members([ null, "https://blahonga.expressen.se/slow-request" ]); + expect(results[2][2]).to.include({ priority: "low" }); }); describe("redirect", () => {