只有在刷新页面后,才能看到firebase存储中的更新记录

时间:2016-10-28 12:11:28

标签: javascript node.js asynchronous

在firebase中编辑我的收藏中的记录并更改图像时,它将在Firebase和Google Cloud Platform(存储)中成功更新,但在模板中,除非我刷新页面,否则我无法看到更改。我得到的错误是:Error: Can't set headers after they are sent.

router.get('/edit/:id', function(req, res) {
  var id = req.params.id;
  firebase.database().ref(`collection/` + id).once('value')
    .then(function(data) {
      res.render('myEditTemplate', {
        id: id,
        collectionRecords: data.val()
      });
    })
    .catch(function(error) {
      res.render('error', {
        error: error
      });
    });
});

router.post('/edit', upload.single('image'), function(req, res) {
  var id = req.body.id;
  var name = req.body.name;
  var image = req.file;

  if (!req.file) {
    console.log('no image has been uploaded');

    firebase.database().ref(`collection/` + id).update({
      'name': name,
    });
  } else {
    console.log('image successfully uploaded');

    var filePath = id + ".jpg";

    fs.rename(req.file.path, filePath, function(err) {
      if (err) {
        return res.render("error", {
          err: err
        });
      }

      var myPath = 'collection/' + filePath;
      var storageFile = bucket.file(myPath);
      var storageFileStream = storageFile.createWriteStream({
        metadata: {
          contentType: req.file.mimetype
        }
      });

      storageFileStream.on('error', function(err) {
        return res.render("error", {
          error: err
        });
      });

      storageFileStream.on('finish', function() {
        storageFile.makePublic(function(err, data) {

          if (err) {
            return res.render("error", {
              err: err
            });
          }
        });

        fs.unlink(filePath, function(err) {

          console.error(err);
        });

        firebase.database().ref(`collection/` + id).update({
          'name': name,
          'image_id': filePath
        });
      });
      fs.createReadStream(filePath).pipe(storageFileStream);
    });
  }
  res.redirect('/collection');
});

1 个答案:

答案 0 :(得分:1)

当您收到此类错误时,表示您多次向客户端发送响应(具体而言,设置标题)。

在这种情况下,错误的来源是您res.redirect(...)res.render(...)

router.post('/edit', upload.single('image'), function(req, res) {
  var id = req.body.id;
  var name = req.body.name;
  var image = req.file;
  ...
    // Eventually update the file in Google Cloud Storage
    // This happens in an async way.
  ...

  // This will be always called first
  res.redirect('/collection');
});

如果来自异步操作的错误,您将收到您提到的错误。它只是无法呈现错误模板,因为已经做了redirect(...)

您当前的时间表如下所示:

           ___ Update the image in GC __
          /                             \
|--*-----*--*----------------------------*------>
   |        |                         Is there an error?
 Request    |                             If so, res.render(...)
            |                             Rendering the error template
      res.redirect(...)                   will always fail due to the
            |                             previous res.redirect(...)
            |
            V
     You do not see the new image
     at this moment, because it's
     simply not updated yet.

它应该发生的是:

           ___ Update the image in GC __
          /                             \
|--*-----*-------------------------------*------>
   |                                  Is there an error?
 Request                                If so, show the error: 
                                          res.render(...)
                                        If not, do the redirect:
                                        res.redirect(...)
                                         |
                                         V
                                     Since the page is going to load
                                     *after* the image was updated
                                     you will see the updated image.

代码如下所示:

router.post('/edit', upload.single('image'), function(req, res) {
  var id = req.body.id;
  var name = req.body.name;
  var image = req.file;

  if (!req.file) {
    console.log('no image has been uploaded');
    firebase.database().ref(`collection/` + id).update({
      'name': name,
    }).then(function() {
      res.redirect('/collection');
    }).catch(function(err) {
      res.render("error", {
        err: err
      });
    })
  } else {
    console.log('image successfully uploaded');
    var filePath = id + ".jpg";
    fs.rename(req.file.path, filePath, function(err) {
      if (err) {
        return res.render("error", {
          err: err
        });
      }

      var myPath = 'collection/' + filePath;
      var storageFile = bucket.file(myPath);
      var storageFileStream = storageFile.createWriteStream({
        metadata: {
          contentType: req.file.mimetype
        }
      });

      storageFileStream.on('error', function(err) {
        return res.render("error", {
          error: err
        });
      });

      storageFileStream.on('finish', function() {
        storageFile.makePublic(function(err, data) {
          if (err) {
            return res.render("error", {
              err: err
            });
          }
          res.redirect('/collection');
        });

        fs.unlink(filePath, function(err) {
          console.error(err);
        });

        firebase.database().ref(`collection/` + id).update({
          'name': name,
          'image_id': filePath
        });
      });
      fs.createReadStream(filePath).pipe(storageFileStream);
    });
  }
});