78 lines
2.9 KiB
JavaScript
78 lines
2.9 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import http from 'node:http'
|
|
import axios from 'axios'
|
|
import { createLatestRequest } from './latestRequest.js'
|
|
|
|
test('replacing and closing a query aborts it and invalidates late callbacks', () => {
|
|
const scope = createLatestRequest()
|
|
const first = scope.start()
|
|
let aborted = 0
|
|
first.signal.addEventListener('abort', () => aborted++)
|
|
const second = scope.start()
|
|
assert.equal(aborted, 1)
|
|
assert.equal(first.isCurrent(), false)
|
|
assert.equal(second.isCurrent(), true)
|
|
scope.cancel()
|
|
scope.cancel()
|
|
assert.equal(second.signal.aborted, true)
|
|
assert.equal(second.isCurrent(), false)
|
|
const reopened = scope.start()
|
|
assert.equal(reopened.signal.aborted, false)
|
|
assert.equal(reopened.isCurrent(), true)
|
|
})
|
|
|
|
test('a late response or finally callback cannot overwrite the newly opened query', async () => {
|
|
const scope = createLatestRequest()
|
|
let resolveOld, resolveNew
|
|
const oldResponse = new Promise(resolve => { resolveOld = resolve })
|
|
const newResponse = new Promise(resolve => { resolveNew = resolve })
|
|
let data = null, loading = false
|
|
const load = async response => {
|
|
const request = scope.start()
|
|
loading = true
|
|
try {
|
|
const result = await response
|
|
if (request.isCurrent()) data = result
|
|
} finally { if (request.isCurrent()) loading = false }
|
|
}
|
|
const old = load(oldResponse)
|
|
scope.cancel()
|
|
const current = load(newResponse)
|
|
resolveOld('old channel')
|
|
await old
|
|
assert.equal(data, null)
|
|
assert.equal(loading, true)
|
|
resolveNew('new channel')
|
|
await current
|
|
assert.equal(data, 'new channel')
|
|
assert.equal(loading, false)
|
|
})
|
|
|
|
test('axios cancellation releases the slow HTTP request without cancelling another query', async t => {
|
|
const pending = new Map()
|
|
let ready
|
|
const bothConnected = new Promise(resolve => { ready = resolve })
|
|
const server = http.createServer((req, res) => {
|
|
pending.set(req.url, res)
|
|
if (pending.size === 2) ready()
|
|
})
|
|
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
|
|
t.after(() => { server.closeAllConnections(); server.close() })
|
|
const firstScope = createLatestRequest(), secondScope = createLatestRequest()
|
|
const first = firstScope.start(), second = secondScope.start()
|
|
const base = `http://127.0.0.1:${server.address().port}`
|
|
const cancelled = axios.get(`${base}/slow`, { signal: first.signal })
|
|
const cancellation = assert.rejects(cancelled, error => axios.isCancel(error) && !error.response)
|
|
const completed = axios.get(`${base}/other`, { signal: second.signal })
|
|
await bothConnected
|
|
const disconnected = new Promise(resolve => pending.get('/slow').on('close', resolve))
|
|
firstScope.cancel()
|
|
await cancellation
|
|
await disconnected
|
|
assert.equal(second.isCurrent(), true)
|
|
assert.equal(second.signal.aborted, false)
|
|
pending.get('/other').end('other query finished')
|
|
assert.equal((await completed).data, 'other query finished')
|
|
})
|