Ensuring the completion of fs.createWriteStream before proceeding with the function is vital to prevent only a portion of the image from being

I am trying to improve the performance of my application by saving images from an API response to a MongoDB database for future use, instead of making repeated requests.

Currently, I have implemented a system where I retrieve the image path from the API and use fs.createWriteStream() to save the file. However, when I try to create a "Character" using this saved image, only a portion of the image is being saved before the code moves on to the next step.

I have attempted to make the function asynchronous and used await before making the URL request. I also tried alternative methods like writeFileSync(), but with no success.

Is there a way to ensure that the entire image file is fully written to disk before continuing with the MongoDB update?


 let imagePath = req.body.characterObject.thumbnail.path + '.' + req.body.characterObject.thumbnail.extension;

 let superPath = './uploads/marvelousImage.jpg';
let marvelousImage;
  axios({
      url: imagePath,
      responseType: 'stream',
  })
  .then(response => {
      marvelousImage = response.data.pipe(fs.createWriteStream(superPath));

  })
  .catch(err => {
      console.log(err)
  });

    User.findOne({  "username": "administrator"})
    .then(user => {
      let characterId = req.body.characterObject.id;
      for(let i = 0; i < user.characters.length; i++) {
        if(characterId == user.characters[i].id) {
          return Promise.reject({
            code: 422,
            message: 'You already have this character!',
            reason: "CharacterDuplicationError"
          });
        }
      }
      console.log(req.body.characterObject);
      Character.create({
          description: req.body.characterObject.description || 'bocho',
          events: req.body.characterObject.events || 'lopo',
          thumbnail: req.body.characterObject.thumbnail || 'goso',
          name: req.body.characterObject.name || 'John Doe',
          id: req.body.characterObject.id,
          "image.data": fs.readFileSync(superPath),
          "image.contentType": 'image/jpeg'
      })
      .then(char => {
          console.log('lalala');
          console.log(char);
        user.characters.push(char);
        user.save();
        return res.status(201).json({message: "Character Added!"})
      })
    .catch(err => {
        if(err.reason === "CharacterDuplicationError") {
          return res.send(err);
        } 
    })
   })
 });

Answer №1

It appears that this is not the sole issue at hand, but it is certainly one of them.

Take a look at this piece of code:

  .then(response => {
      marvelousImage = response.data.pipe(fs.createWriteStream(superPath));

  })

The promise chain does not wait for the pipe operation to complete before proceeding. To address this, you must return a promise from the .then() handler that resolves once the reading/writing process finishes. This can be achieved by monitoring events on the writeStream. As .pipe() returns the write stream, we can leverage this return value to establish event handlers and utilize these events to resolve/reject a promise that we subsequently return. Doing so will ensure that the promise chain pauses until the streaming operation concludes before moving on to the next .then() in the chain.

 .then(response => {
     return new Promise((resolve, reject) => {
         marvelousImage = response.data.pipe(fs.createWriteStream(superPath));
         marvelousImage.on('error', reject).on('close', resolve);
     });
  });

Furthermore, I noticed that you initiate your database tasks outside of the promise chain. These operations should be encapsulated within the promise chain itself.

To streamline the code and improve error handling, I made an effort to integrate everything into the promise chain as follows:

let imagePath = req.body.characterObject.thumbnail.path + '.' + req.body.characterObject.thumbnail.extension;
let superPath = './uploads/marvelousImage.jpg';

axios({
    url: imagePath,
    responseType: 'stream'
}).then(response => {
     return new Promise((resolve, reject) => {
         let marvelousImage = response.data.pipe(fs.createWriteStream(superPath));
         marvelousImage.on('error', reject).on('close', resolve);
     });
}).then(() => {
    return User.findOne({"username": "administrator"});
}).then(user => {
    let characterId = req.body.characterObject.id;
    for (let i = 0; i < user.characters.length; i++) {
        if (characterId == user.characters[i].id) {
            return Promise.reject({
                code: 422,
                message: 'You already have this character!',
                reason: "CharacterDuplicationError"
            });
        }
    }
    console.log(req.body.characterObject);
    return Character.create({
        description: req.body.characterObject.description || 'bocho',
        events: req.body.characterObject.events || 'lopo',
        thumbnail: req.body.characterObject.thumbnail || 'goso',
        name: req.body.characterObject.name || 'John Doe',
        id: req.body.characterObject.id,
        "image.data": fs.readFileSync(superPath),
        "image.contentType": 'image/jpeg'
    });
}).then(char => {
    console.log('lalala');
    console.log(char);
    user.characters.push(char);
    user.save();
    return res.status(201).json({
        message: "Character Added!"
    })
}).catch(err => {
    console.log(err);
    if (err.reason === "CharacterDuplicationError") {
        res.send(err);
    } else {
        res.sendStatus(500);
    }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is this accessible within a function?

When attempting to pass a reference to a class through to a method in order to access a variable, I encountered a few issues: My initial attempt looked like this: p.id = 1; p._initEvents = function(){ $('#file-form').on('valid.fndtn.ab ...

What is the best way to ensure an inline-block element spans the entire width?

Is there a way to make an inline block fill the entire width without using !important in AMP? I have tried making all fields fit the whole width but it's not working. How can I achieve this without resorting to !important? Below is the code I am curre ...

Tips for creating a jquery modal form that can be reused

I currently have the following files : *vehicule_parc.php :* <script language=javascript src="../js/vehicule_parc.js"></script> <h3 class="headInfoBox" id="cch">Fuel Consumption >></h3> <hr /> <div id="cc"> ...

Can you effectively utilize jQuery / javascript to parse an HTML table and send the data from each row for database updates?

My task involves loading members into a database from a table that has been populated with data from an MS Excel spreadsheet. The issue I am facing is that the ajax call to write the second row is using data from the first row. Strangely, adding an "alert" ...

Incorporate Node.js seamlessly into your WordPress website for enhanced functionality

Seeking Assistance I am relatively new to javascript, but I have successfully created a flight search single page application using nodejs, angularjs, and the Skyscanner API. Now, my goal is to integrate this application as an embedded website within a W ...

Querying a mini database using MongoDB

I am currently managing a MongoDB database with around 250 million documents. The main collection holds the bulk of the data and is indexed on time, providing efficient query times when using time in the query. However, I am facing difficulties when trying ...

Having trouble updating the input value in AngularJS?

As I venture into customizing an AngularJS tutorial on a Saturn Quiz, I am transforming it from multiple choice to a fill-in-the-blank quiz. The challenge I face is that the first answer registers as correct or incorrect, but subsequent questions always s ...

Uncovering classes and selectors in CSS files that match an element with JavaScript

Trying to explain my idea with an example since it's a bit tricky. Imagine we have this HTML code: <ul> <li id="myli" class="myclass">Hello</li> </ul> along with the corresponding CSS: .myclass{ color:red; } li.m ...

What is the best way to turn a calendar table's <td> elements into interactive form elements?

I am currently working on developing an events booking form, but I am facing a challenge. I want users to be able to click on a specific date in a table cell representing a calendar to select their start date. However, my expertise lies more in PHP progra ...

Tips for pre-selecting default text in ng-select or ng-options component?

I'm new to AngularJS and I've been looking for solutions here without any luck. I have a json file from a controller that I'm displaying in a select element. I want to set the selected value based on the text value. This is my current progre ...

View the unprocessed data as a visual image right in the chrome browser

After receiving a raw buffer from an API call, I am encountering issues when trying to display the image directly in the browser. Instead of displaying the image, it is simply downloading as a raw file. Can someone provide guidance on how to resolve this ...

What is the best way to showcase the current date and time on a web browser

Currently working on a nodejs express application where dates are stored in the database using UTC date/time. Want to display the date/time in the user's local time zone. Any ideas on how I could go about implementing this? Appreciate any assistance. ...

What is the process for integrating ion-tabs with IonicVueRouter within an Ionic (vue.js) application?

My Project Idea I have a vision to create an innovative exercise warm-up application. The app will be divided into two main sections: a workout tab and a settings tab. The user journey will start with selecting a workout plan, then choosing specific exerc ...

Activate jQuery after a vanilla JavaScript function has been executed

I have created a jQuery function that captures any changes made to an input field and stores them in a variable. The input field is connected to a vanilla JavaScript based API library, which I am unable to convert to jQuery. This library is for an address ...

Obtain access to global.window.localStorage within getServerSideProps

I have a component that receives props with data and renders the data. In my functionality within the getServerSideProps, I am attempting to retrieve data from localStorage. However, due to window being undefined, I am unable to do so. I have tried using ...

Refine your search by name following the implementation of a character-altering filter

Encountered a scenario in which there is a need to filter elements generated by the 'ng-repeat' directive. I have implemented a custom filter that replaces one character with another and vice versa for each element created. However, when attempt ...

Is there a more efficient method for iterating through this object?

Working with JSON and JS var data = { "countries": { "europe" : [{name: "England", abbr: "en"}, {name: "Spain", abbr: "es"}], "americas" : [{name: "United States"}], "asia" : [{name: "China"}] } }; JavaScript Loop for (k in data) { fo ...

Is there a way to automatically update the URL to include $_GET['data'] (media.php?data=123) when a selection is made from a dropdown list?

I'm currently working on a project that involves a website in PHP and a MySQL database. I have successfully linked the two together, and now I have a combobox filled with data from the database. Below is my script for handling the selection: <scr ...

Having difficulty kicking off a fresh React project on Windows

I've encountered an issue while setting up my React application on Windows OS. After running npm start, the application fails to load on localhost:3000, showing the error message Cannot GET /. Below is the project structure: - webpack.config.js - p ...

Failure occurs when attempting to utilize external .js and .css files

As I embark on creating a website using Bootstrap, I stumbled upon a registration page code that consists of three files - HTML, CSS, and .js. registration.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> ...