javascriptbase64array-mapasynchronous-javascript

Mapping over array of object with promises


I need to map over array of objects and change "photo property" in every object into it's base64 representation from the url im storing in databse. For this purpose I'm using imageToBase64 library for node.js. But the problem is I cannot generate the same array with just changed properties. Tried lot of times with destructuring, returning in different ways and I still got either undefined or unchanged array. What is more when I console log as shown in code block, it logs correctly changed objects but in different order (second user go first in console and first user go second). Where's the problem and how to just get the same array but with converted "photo property in every object" to be able to send it over http? Here's my code:

const getUsers = asyncHandler(async (req, res) => {
  const userRecords = await userRecord.find({ appUser: req.appUser.id });
  const convertedRecords = userRecords.map((record) => {
    imageToBase64(record.photo)
      .then((response) => {
        record.photo = response
        console.log(record)
      })
      .catch((error) => {
        console.log(error);
      });
      //SHOULD RETURN SOMETHING
      
  });
  
  res.status(200).json(userRecords);
});

And this is how my schema looks like:

const userRecordSchema = mongoose.Schema(
  {
    appUser: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: "appUser",
    },
    firstName: {
      type: String,
    },
    lastName: {
      type: String,
    },
    email: {
      type: String,
    },
    age: {
      type: Number,
    },
    photo: {
      type: String,
    }
  },
  {
    timestamps: true,
  }
);

module.exports = mongoose.model("UserRecord", userRecordSchema);

Solution

  • If think you need to add some return :

    const getUsers = asyncHandler(async (req, res) => {
        const userRecords = await userRecord.find({ appUser: req.appUser.id });
        const convertedRecords = await Promise.all(userRecords.map((record) => {
          return imageToBase64(record.photo) // return the result of convertion
            .then((response) => {
                return {...record, _doc: {...record._doc, photo: response} }; // return the re structured object instead of modify
            })
            .catch((error) => {
              console.log(error);
            });
            //SHOULD RETURN SOMETHING
            
        }));
    
        console.log(convertedRecords); // should print the expected result
        
        res.status(200).json(userRecords);
      });
    

    You need to add a return statement inside a .map callback.
    Also, when you need to return the edited record, just edit the record will not change the result of imageToBase64.

    I'm not 100% sure as I can't test your code, but I think this can helps you