J'utilise Observable (Rxhttp en particulier). J'utilise également connect-timeout pour des demandes de longue durée. Malheureusement, mon .subscribe
semble toujours fonctionner, même lorsque le middleware de gestion des erreurs a été touché, et aurait dû fermer la connexion.Utilisation d'observables dans le routage express Le middleware provoque le paramétrage des en-têtes après leur envoi.
Il en résulte souvent un: Error: Can't set headers after they are sent.
Un cas reproductible minimale est inférieure.
'use strict'
const express = require('express')
const timeout = require('connect-timeout')
const Rx = require('rx')
const http = require('http')
let app = express()
app.use(timeout('1s'))
app.get('/', (req, res) => {
//in the real application the Rx is an external request
return Rx.Observable.create((observer) => {
observer.onNext({
response: 'potato'
})
observer.onCompleted()
})
.delay(new Date(Date.now() + 1500))
.subscribe((x) => {
console.log('this runs')
res.status(200).send()
}, (e) => {
console.log('this does not')
})
})
app.use((err, req, res, next) => {
if(err) {
res.status(500).send('SOMETHING BROKE!')
}
})
const httpServer = http.createServer(app)
httpServer.listen(3000, function() {
console.log('Listening on port %d.', 3000)
})
Comment éviter ce problème? Pourquoi le .subscribe
est-il toujours en cours d'exécution même si le middleware a expiré? Je sais que je peux éviter cela en enchaînant un .timeout
sur l'observable, mais cela a l'inconvénient qu'il ne correspond pas nécessairement au délai d'attente de connexion (par exemple, une lecture de base de données aurait pu se produire, la demande globale aurait pu prendre plus d'un en second lieu, alors que l'observable lui-même ne le fait pas). Existe-t-il une solution plus générique?
Je suis désolé je n'ai pas été clair, mon retard simule délibérément le cas de minutage, mais l'abonnement fonctionne encore ... –
C'est parce que subscribe est censé fonctionner après le délai, son gestionnaire d'erreur ne l'est pas. @AbrahamP – turmuka