0

for dropping by.

i have problem that i'd like to share and hopefuly be able to share toughts and tricks with you, first and foremost here's what my whole function looks like :

async function get(req, res) {
  const pagination = simplePagination(req);

  let result = [];
  let dataChat = [];
  await chatModel.updateMany({
      user_id: req.query.user_id,
      platform_id: req.query.platform_id,
      vendor_id: req.query.vendor_id,
    }, {
      read: 1,
      updated_At: new Date(),
    })
    .then(() => chatModel.find({
        user_id: req.query.user_id,
        platform_id: req.query.platform_id,
        vendor_id: req.query.vendor_id,
      })
      .sort({
        created_At: 'asc'
      })
      // eslint-disable-next-line radix
      .skip(parseInt(pagination.page))
      .limit(parseInt(pagination.row))
      .lean()
      .then(async(data) => {
        dataChat = data;
      })
      .catch((err) => {
        // console.log(err, '<<<< dimana errornya');
        setContent(500, errorCode.generalError.SYSTEM_ERROR);
        return res.status(500).json(getContentFail(req, err));
      }));

  dataChat.forEach((element) => {
    if (element.chat_type === 'negotiation') {
      dbPlatform.findByPk(element.platform_id, {
          include: [{
            model: dbPlatform_image,
            order: [
              ['created_at', 'asc']
            ],
            limit: 1,
          }],
        })
        // eslint-disable-next-line no-loop-func
        .then((dataPicture) => {
          element.data = dataPicture;
          result.push(element);
          console.log(element, '<< ASD COBA CEK');
        })
        .catch((err) => {
          setContent(500, errorCode.generalError.SYSTEM_ERROR);
          return res.status(500).json(getContentFail(req, err));
        });
    }
  });

  setContent(200, result);
  await res.status(200).json(getContentSuccess());
}

ok let's break down and let me explain in a brief what my problem, intention and expectation.

as you guys can see at this part :

let result = [];
let dataChat = [];

await dataChat.forEach((element) => {
    if (element.chat_type === 'negotiation') {
        dbPlatform.findByPk(element.platform_id,
            {
                include: [{
                    model: dbPlatform_image,
                    order: [['created_at', 'asc']],
                    limit: 1,
                }],
            })
            // eslint-disable-next-line no-loop-func
            .then((dataPicture) => {
                element.data = dataPicture;
                result.push(element);
                console.log(element, '<<<< check element');
                console.log(result, '<<<<<< resultnya');
            })
            .catch((err) => {
                setContent(500, errorCode.generalError.SYSTEM_ERROR);
                return res.status(500).json(getContentFail(req, err));
            });
    }
});

setContent(200, result);
await res.status(200).json(getContentSuccess());

i'm successfully able to push the result from chat model find to dataChat variable and after that my goal is to loop dataChat variable using for each, to create and modify using condition in my loop and push it to result variables and then to returned as this part shows

dataChat.forEach((element) => {
    if (element.chat_type === 'negotiation') {
        dbPlatform.findByPk(element.platform_id,
            {
                include: [{
                    model: dbPlatform_image,
                    order: [['created_at', 'asc']],
                    limit: 1,
                }],
            })
            // eslint-disable-next-line no-loop-func
            .then((dataPicture) => {
                element.data = dataPicture;
                result.push(element);
                console.log(element, '<< ASD COBA CEK');
            })
            .catch((err) => {
                setContent(500, errorCode.generalError.SYSTEM_ERROR);
                return res.status(500).json(getContentFail(req, err));
            });
    }
});

setContent(200, result);
await res.status(200).json(getContentSuccess());

the problem is instead of returning the result variables that already modify, it returning empty array and passing the for each loop, i already try to put await before just like this :

    await dataChat.forEach((element) => {
    if (element.chat_type === 'negotiation') {
        dbPlatform.findByPk(element.platform_id,
            {
                include: [{
                    model: dbPlatform_image,
                    order: [['created_at', 'asc']],
                    limit: 1,
                }],
            })
            // eslint-disable-next-line no-loop-func
            .then((dataPicture) => {
                element.data = dataPicture;
                result.push(element);
                console.log(element, '<< check element');
            })
            .catch((err) => {
                setContent(500, errorCode.generalError.SYSTEM_ERROR);
                return res.status(500).json(getContentFail(req, err));
            });
    }
});

but it doesn't help and keep passing directly and returning empty array with result like this

{ "response": 200, "result": [] }

i already check the result from this for each loop using console log in my terminal like this :

            .then((dataPicture) => {
                element.data = dataPicture;
                result.push(element);
                console.log(element, '<<<< check element')
                console.log(result, '<<<< check result')


            })

it shows that the element data has been successfully modified and the result also already successfully modified with the data from element but unfortunately it decide to pass the process and directly returning not yet modify result variable resulting me getting empty array.

FYI i'm using mongoose (MongoDB) and sequelize (Postgres) method in this function

thank you for dropping by and good day :)

Barmar
  • 741,623
  • 53
  • 500
  • 612

2 Answers2

0

The problem is your forEach part. Promise or async/await deosn't work in forEach. You need to either use Promise.all if you can do things in parallel or use for..of if you want to do sequentially.

await Promise.all(dataChat.map(element => {
  if (element.chat_type === "negotiation") {
    return dbPlatform.findByPk(element.platform_id, {
      "include": [{
        "model": dbPlatform_image,
        "order": [
          ["created_at", "asc"]
        ],
        "limit": 1
      }]
    })
      // eslint-disable-next-line no-loop-func
      .then(dataPicture => {
        element.data = dataPicture;
        result.push(element);
        console.log(element, "<< ASD COBA CEK");
      })
      .catch(err => {
        setContent(500, errorCode.generalError.SYSTEM_ERROR);
        return res.status(500).json(getContentFail(req, err));
      });
  }
}));

If you want to do things sequentially

for (const element of dataChat) {
  if (element.chat_type === "negotiation") {
    const dataPicture = await dbPlatform.findByPk(element.platform_id, {
      "include": [{
        "model": dbPlatform_image,
        "order": [
          ["created_at", "asc"]
        ],
        "limit": 1
      }]
    });
    element.data = dataPicture;
    result.push(element);
    console.log(element, "<< ASD COBA CEK");
  }
}

Hope this helps

Ashish Modi
  • 7,529
  • 2
  • 20
  • 35
0

Don't mix await syntax with then calls, and don't use forEach. You're looking for

async function get(req, res) {
  const pagination = simplePagination(req);

  try {
    await chatModel.updateMany({
      user_id: req.query.user_id,
      platform_id: req.query.platform_id,
      vendor_id: req.query.vendor_id,
    }, {
      read: 1,
      updated_At: new Date(),
    });

    const dataChat = chatModel.find({
      user_id: req.query.user_id,
      platform_id: req.query.platform_id,
      vendor_id: req.query.vendor_id,
    })
    .sort({
      created_At: 'asc'
    })
    .skip(parseInt(pagination.page, 10))
    .limit(parseInt(pagination.row, 10))
    .lean();

    const result = await Promise.all(dataChat.filter(element =>
      element.chat_type === 'negotiation'
    ).map(async (element) => {
      const dataPicture = await dbPlatform.findByPk(element.platform_id, {
        include: [{
          model: dbPlatform_image,
          order: [
            ['created_at', 'asc']
          ],
          limit: 1,
        }],
      });
      element.data = dataPicture;
      console.log(element, '<< ASD COBA CEK');
      return element;
    }));
    setContent(200, result);
    res.status(200).json(getContentSuccess());
  } catch(err) {
    // console.log(err, '<<<< dimana errornya');
    setContent(500, errorCode.generalError.SYSTEM_ERROR);
    res.status(500).json(getContentFail(req, err));
  }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375