Jean-Philippe Dufour
Jean-Philippe Dufour

Reputation: 151

Response sent is 1 response late

The response I receive from my Node.js server is always 1 response late. I will always receive the response I should have received the time I pressed that Upload button.

When Node server jus started, response is empty. Been trying countless things in the past four hours and I can't figure it out.

I switched from bodyParser to a library called express-busboy for files upload because I didn't have to re-write my entire code. Everything else in my app still works fine so I'm starting to think the problem might be related to the file upload part of the library.

This is my Node Code, sorry it might be a bit tedious to read but I am really lost here and this is the only thing preventing me from going forward.

This is the code for my backend.

import * as fse from 'fs-extra';

export default class PhotoController{

  private postError = [];
  private postSuccess = [];

  public postPhotos =  (req, res) => {
    const fileArray = Array.isArray(req.files.file) ? req.files.file : new Array(req.files.file);
    const body = new Array(req.body);
    const item = body[0].item;
    const staticFileDest = `C:\\Users\\JP\\Desktop\\MiMApp\\MiMBackEnd\\movedUploads`;
     for (let i = 0; i < fileArray.length; i++){
      const removeDest = `./uploads/${fileArray[i].uuid}`;
      const newName =  Array.isArray(body[0].newName)? body[0].newName[i] : body[0].newName;
      const srcFile = `./${fileArray[i].file}`;
      const moveDest = `${staticFileDest}\\${item}\\${newName}`;
       fse.pathExists(moveDest)
        .then(exists => {
          if (exists){
          this.postError.push(`Fichier ${newName} existe deja.`);
          this.removeSrcFile(removeDest);
          } else {
            fse.move(srcFile, moveDest)
              .then( () => {
                const commentToAdd = Array.isArray(body[0].comment) ? body[0].comment[i] : body[0].comment;
                const commentPath = moveDest.replace(/\.[^/.]+$/, "").concat('.txt');
                this.postSuccess.push(`Fichier ${newName} à été ajouté dans l'item : ${item}`);
                this.removeSrcFile(removeDest);
                fse.writeFile(commentPath, commentToAdd)
                  .then(() => {this.postSuccess.push(`Le commentaire à été ajouté pour ${newName}`)})
                  .catch(() => {this.postError.push(`Le commentaire pour ${newName} existe deja.`)});
              })
              .catch(() => {
                this.postError.push(`Le fichier ${newName} n'a pas été rajouté correctement.`);
               this.removeSrcFile(removeDest);
               this.removeSrcFile(moveDest);
              });
           }
        });
     }
      this.sendResponse(res);
      this.resetErrors();
  };

  private removeSrcFile(file){
    fse.remove(file)
      .then(() => {})
      .catch(() => {this.postError.push(`${file} n'a pas pu être éffacé.`)});
  }

  private resetErrors(){
    this.postError = [];
    this.postSuccess = [];
  }

  private sendResponse(res){
    if (this.postError.length > 0){
      res.send({success : this.postSuccess, errors : this.postError});
    } else {
      res.send({success: this.postSuccess});
    }

  }

}

Frontend :

onUpload()
  {
    const filesToUpload = new FormData();
    for (const values of this.selectedFile){
      filesToUpload.append('file', values.file);
      filesToUpload.append('newName', values.name);
      filesToUpload.append('comment', values.comment ? values.comment : 'Aucun commentaire.');
    }
    filesToUpload.append('item', this.itemNumber);
    this.photoService.postPictures(filesToUpload)
        .subscribe(
            res => {
              if (res){
                this.postResponse = res;
              } else {
                this.openUnexpectedModal();
              }
            },
            err => {
              this.openUnexpectedModal();
            },
            () => {
              this.openResponseModal();

            }
        )
  }

Service :

export class PhotoService {

    constructor(private http: HttpClient, private config: Config) {}

    public postPictures = (datas): Observable<any> => {
        return this.http.post(`${this.config.apiAddress}/postPictures`, datas)
            .pipe(
                map(data => {return data})
            );
    }
}

First response when I submit :

{"success":[]}

if I submit again :

{"success":["Fichier 15012019-YEDwo.jpg à été ajouté dans l'item : 55","Le commentaire à été ajouté pour 15012019-YEDwo.jpg"]}

Upvotes: 0

Views: 39

Answers (1)

J. S.
J. S.

Reputation: 2376

You execute an asynchrounus function but your send function this.sendResponse(res); is fired synchrounus.

 fse.move(srcFile, moveDest)
              .then( () => {
                ...
}

That means while fse.move is running you already have sent your request while this.postSuccess was just an empty array initialized here private postSuccess = [];. The second time fse.move is finished that is why your response is filled with data.

Upvotes: 1

Related Questions