2017-10-10 7 views
1

J'essaie de mettre en œuvre une fonction middleware assez simple à mon application Express qui ajoute simplement une valeur useCache à l'objet de requête étant passé au gestionnaire principal, mais pour une raison quelconque, je reçois un Can't set headers after they were sent Erreur.Erreur de l'en-tête Express Middleware Définition

const cacheControl = (req, res, next) => { 
    if (lastPulled === null) lastPulled = Date().getDay() 
    req.useCache = Date().getDay() === lastPulled 
    next() 
} 

app.use(cacheControl) 
app.get('/missions', (req, res) => { 
    if (req.useCache) res.status(200).json({ result: cache }) 

    fetch(dumpUrl) 
    .then(data => data.text()) 
    .then(result => { 
     cache = result 
     res.status(200).json({ result }) 
    }) 
    .catch(e => res.status(500).json({ result: e.message })) 
}) 

J'ai lu que la plupart du temps si l'erreur est produite par le middleware est dû à plusieurs next() appels, mais cela ne s'applique pas ici, à moins que je me manque quelque chose évidente.

Lorsque je supprime le middleware cacheControl de l'application, il n'y a plus d'erreur, mais je n'arrive pas à comprendre ce qui cause l'erreur dans la fonction! Tous les pointeurs sont utiles!

Répondre

1

Je devine que c'est parce que res.json() on tire deux fois:

app.get('/missions', (req, res) => { 
    if (req.useCache) res.status(200).json({ result: cache }) 

    fetch(dumpUrl) 
    .then(data => data.text()) 
    .then(result => { 
     cache = result 
     res.status(200).json({ result }) 
    }) 
    .catch(e => res.status(500).json({ result: e.message })) 
}) 

// if res.useCase is true, set headers and reply 
if (req.useCache) res.status(200).json({ result: cache }) 

// then fetch and reply again (which generates the error) 
fetch(dumpUrl) 
    .then(data => data.text()) 
    .then(result => { 
     cache = result 
     res.status(200).json({ result }) 

changement à ce à utiliser retour explicite

app.get('/missions', (req, res) => { 
    if (req.useCache) return res.status(200).json({ result: cache }) 

    return fetch(dumpUrl) 
    .then(data => data.text()) 
    .then(result => { 
     cache = result 
     res.status(200).json({ result }) 
    }) 
    .catch(e => res.status(500).json({ result: e.message })) 
}) 

La nature de l'erreur est similaire à quand vous faites ceci:

problème

function problem() { 
 
     if (true === true) console.log('send problem') 
 
     console.log('send garbage by accident') 
 
    } 
 
    console.log(problem())

solution

function solution() { 
 
     if (true === true) return console.log('send solution') 
 
     return console.log('send nothing') 
 
    } 
 
    console.log(solution())

return comment vous quittez une fonction. Votre problème est que votre code vérifiait la condition if, mais continuait alors, car il n'était pas dit d'arrêter une fois qu'il avait trouvé cette condition.

L'ancienne façon ou moins laconique d'écrire votre fonction serait comme:

app.get('/missions', (req, res) => { 
    if (req.useCache) { 
    res.status(200).json({ result: cache }) 
    } else { 
    fetch(dumpUrl) 
     .then(data => data.text()) 
     .then(result => { 
     cache = result 
     res.status(200).json({ result }) 
     }) 
     .catch(e => res.status(500).json({ result: e.message })) 
    } 
}) 

Sans else là-dedans, il exécute chaque instruction if qu'il rencontre jusqu'à la fin de la fonction, à moins que vous utilisez le mot-clé return comme repère pour quitter la page. Gardez à l'esprit, en utilisant return à l'intérieur d'une fonction .then() résoudra la promesse, il ne sortira pas de la portée supérieure s'il y a plus .then() s enchaîné sur.