Действительно борется с обещаниями (Невозможно установить заголовки после их отправки клиенту) - PullRequest
0 голосов
/ 11 января 2020

За последнюю неделю я усердно работал, чтобы обернуть голову обещаниями, но все еще не думаю, что полностью их понимаю. Я переписывал следующую функцию около 6 раз и все еще получаю ошибку «Невозможно установить заголовки после того, как они отправлены клиенту». Я нашел несколько сообщений на эту топи c, но до сих пор не могу понять:

  1. Ошибка: невозможно установить заголовки после их отправки клиенту
  2. Невозможно установить заголовки после их отправки клиенту
  3. Ошибка: настройка заголовка после его отправки - помогите мне понять, почему?

Если у кого-то есть время или терпение объяснить, почему я все еще получаю ошибку, это было бы очень ценно ... Я начинаю вырывать свои волосы. Функция предназначена для форума и запускается при отправке комментария. Он проверяет, существует ли сообщение на форуме, чем если существует родительский комментарий (в случае, если это подкоммент). Я использую firestore.

index. js

const functions = require('firebase-functions');
const app = require('express')();
const {postOneForumComment,
} = require('./handlers/forumPosts');

app.post('/forumPost/:forumPostId/:parentId/comment', FBAuth, postOneForumComment);

exports.api = functions.https.onRequest(app);

forumPosts. js

// submit a new comment
exports.postOneForumComment = (req, res) => {
  if (req.body.body.trim() === '')
  return res.status(400).json({ comment: 'Must not be empty' });

 const newComment = {
   body: req.body.body,
   forumPostId: req.params.forumPostId,
   parentId: req.params.parentId
 };

 db.doc(`/forumPosts/${req.params.forumPostId}`)                  //check to see if the post exists
   .get()
   .then((doc) => {
     if (!doc.exists) {
       return res.status(404).json({ error: 'Post not found' });
     }
     else if (req.params.forumPostId !== req.params.parentId) {   //check to see if the comment is a subcomment
       return db.doc(`/forumComments/${req.params.parentId}`)     //check to see if the parent comment exists
         .get();
     }
     return "TopLevelComment";
   })
   .then((data) => {
     if (data === 'TopLevelComment' || data.exists) {
       return db.collection('forumComments').add(newComment);     //post the comment to the database
     }
     return res.status(500).json({ error: 'Comment not found' });
   })
   .then(() => {
     res.json(newComment);
   })
   .catch((err) => {
     console.log(err.message);
     res.status(500).json({ error: 'somethign went wrong' });
   });
 };

ОШИБКА:

(узел: 29820) UnhandledPromiseRejectionWarning: необработанное отклонение обещания. Эта ошибка возникла либо из-за того, что внутри asyn c -функции возникла ошибка без блока catch, либо из-за отклонения обещания, которое не было обработано с помощью .catch (). (идентификатор отклонения: 1) (узел: 29820) [DEP0018] Предупреждение об устаревании: отклонения необработанного обещания устарели. В будущем отклонения обещаний, которые не обрабатываются, завершат процесс Node.js с ненулевым кодом завершения.

Ответы [ 2 ]

1 голос
/ 11 января 2020

Есть два способа использования обещаний. Либо вы используете обратные вызовы then / catch, либо вы можете использовать async / await, чтобы позволить вам писать их синхронно.

then / catch метод

// Some code before promise

somePromise.then(() => {
    // Some code after promise action is successful
}).catch(err => {
    // Some code if promise action failed
})

// Some code after promise definition you think should run after the above code
// THIS IS WHAT IS HAPPENING WITH YOUR CODE

метод async / await

// Some code before promise
await somePromise;
// Some code after promise action is successful

Последний подход был введен во избежание проблемы ада обратного вызова , и, похоже, именно здесь возникает ваша ошибка.

При использовании обратного вызова В случае обратных вызовов вы должны убедиться, что ничего не определено после определения обещания, иначе оно будет выполнено за до разрешения обещания (что нелогично, поскольку размещение кода B после кода B должно заставить A работать до B)

Ваша ошибка связана с тем, что ваши обратные вызовы, вероятно, выполняются ПОСЛЕ того, как ответ был отправлен, и express не позволяет отправлять несколько ответов на запрос. Вы должны убедиться, что там, где когда-либо вызывается res.send или res.json, существует обратный вызов.

Эта статья должна помочь вам лучше понять обещания ...

Надеюсь, это поможет ...

0 голосов
/ 12 января 2020

Для тех, кто сталкивается с этим, есть рабочее решение, использующее Promise.all, чтобы убедиться, что все обещания выполнены, прежде чем двигаться дальше. Это не самая красивая функция, и я планирую вернуться и превратить ее в суровое испытание / ожидание в соответствии с рекомендациями @kwame и @ Ajay ... но пока она работает.

// post a comment
// TODO: turn into async await function
exports.postOneForumComment = (req, res) => {
  if (req.body.body.trim() === '') return res.status(400).json({ comment: 'Must not be empty' });

  const newComment = {
    body: req.body.body,
    createdAt: new Date().toISOString(),
    forumPostId: req.params.forumPostId,
    parentId: req.params.parentId,
    username: req.user.username,
    userImage: req.user.imageUrl,
    likeCount: 0
  };


  const parentPost =
    db.doc(`/forumPosts/${req.params.forumPostId}`).get()
       .then((doc) => {
         if (!doc.exists) {
           res.status(404).json({ error: 'Post not found' });
           return false;
         }
         return true;
       })
       .catch((err) => {res.status(500).json({ error: 'something went wrong while checking the post' });});

  const parentComment =
    req.params.forumPostId === req.params.parentId ? true :
      db.doc(`/forumComments/${req.params.parentId}`).get()
       .then((doc) => {
         if (!doc.exists) {
           res.status(404).json({ error: 'Comment not found' });
           return false;
         }
         if (doc.forumPostId !== req.params.forumPostId) {
           res.status(404).json({ error: 'Comment is not affiliated with this post' });
           return false;
         }
         return true;
        })
        .catch((err) => {res.status(500).json({ error: 'something went wrong while checking the comment' });});

    Promise.all([parentPost, parentComment])
    .then((values) => {
      if (values[0] && values[1]) {
        return db.collection('forumComments')
        .add(newComment)
        .then(() => {
          res.json(newComment);
        });
      }
      return console.log("there was an error");
    })
    .catch((err) => {
        res.status(500).json({ error: 'somethign went wrong with the submission' });
    });
 };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...