2016-10-28 5 views
1

При редактировании записи в моей коллекции в firebase и изменении изображения она будет успешно обновляться в Firebase и в Cloud Cloud Platform (хранилище), но в шаблоне я не чтобы увидеть изменение, если я не обновляю страницу. Ошибки я получаю: Error: Can't set headers after they are sent.Запись обновления в хранилище firebase отображается только после обновления страницы

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'); 
}); 
+0

Когда вы следующее сообщение об ошибке «Ошибка: невозможно установить заголовки после их отправки». Это означает, что вы пытаетесь отправить ответ на запрос после того, как он уже был en отправлено. В вашем случае вы делаете перенаправление перед выполнением асинхронных задач, поэтому всякий раз, когда у вас есть ошибка, вы пытаетесь отправить второй ответ на запрос. – krakig

ответ

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); 
    }); 
    } 
}); 
Смежные вопросы