-1

The function gets resolved on its own and no data is returned from the function but null. Can anyone solve this for me please?

print is happening like below :

  • [ RowDataPacket { payment_id: 'PAYID-MDRPLBY9LS10853614735924' } ]
  • data not 000000
  • data not 1111111
  • promise2
  • Get Payment Response
  • Payment Object

but it should be :

  • [ RowDataPacket { payment_id: 'PAYID-MDRPLBY9LS10853614735924' } ]
  • data not 000000
  • data not 1111111
  • Get Payment Response
  • Payment Object
  • promise2

async function func(req, res) {
  return new Promise((resolve, reject) => {
    let email_id = req.body.email_id;
    let arr = [];
    let ctr = 0;
    sql_get_orderid =
      "Select payment_id from paypal.execute_order where email_id=?";

    db.query(sql_get_orderid, [email_id]).then(function (data) {
      console.log(data);
      if (data.length != 0) {
        console.log("data not 000000");
        data.forEach((x) => {
          console.log("data not 1111111");
          var paymentId = x.payment_id;
          paypal.payment.get(paymentId, function (error, payment) {
            if (error) {
              console.log(error);
              reject({ auth: true, message: "Error on the Server" });
            } else {
              console.log("Get Payment Response");
              console.log(JSON.stringify(payment));
              arr[ctr] = payment;
              ctr = ctr + 1;
              // resolve(payment);
              // if(ctr==data.length)
            }
          });
        });
        resolve(arr);
      }
    });
  });
}


router.post(
  "/get_all_orders",
  VerifyToken.Token_Verification,
  async (req, res) => {
    let arr = await func(req, res);
    console.log("promise2");
    res.send({ data: arr });
  }
);
  • What do you mean it "gets resolved on its own"? – ray Jul 14 '21 at 15:46
  • that's not how promises work. If it's getting resolved, it's because `resolve` was called. if it's getting resolved with `null`, then `payment` is `null`. – Kevin B Jul 14 '21 at 15:49
  • @rayhatfield if resolve is called then it should return payment object but it does not.I am able to print the payment object..... payment value is got afterwards but the function returns null early. – Abhinav kumar sintoo Jul 14 '21 at 15:51
  • How are you using `getPaymentDetails`? your talk of it "returning early" makes me think you're trying to return data from an async callback. also, it doesn't need the `async` keyword, since you never used await. – Kevin B Jul 14 '21 at 16:01
  • @KevinB have edited the code for ... also have provided the payment id for you to see – Abhinav kumar sintoo Jul 14 '21 at 16:12
  • Yup, that’s your standard trying to return from an asynchronous callback logic error. Your resolve is happening before arr has been populated. – Kevin B Jul 14 '21 at 16:16
  • @KevinB how to solve it ? just criticising wont solve my problem – Abhinav kumar sintoo Jul 14 '21 at 16:25
  • It was meant as something to look for, I’m on mobile atm and can’t easily go find the super dupe. – Kevin B Jul 14 '21 at 16:31
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Kevin B Jul 14 '21 at 17:16

1 Answers1

-1

The reason why your logs are not in the order you expect it to be is that forEach in javascript expects a synchronous callback function. It does not wait for promises or callbacks inside its callback to return. Therfore in your code when func is invoked and once db.query is performed and if data.length is valid data not 000000 is logged. Then iteration begins with forEach. Here for Each element in iteration data not 1111111 will be logged and an asynchronous call is made through paypal.paymeny.get method. As mentioned above, forEach callbacks does not wait for it to get resolved and next iteration is continued and so on. Once iteraions are done, resolve is invoked. By the time when resolve is invoked paypal.paymeny.get has not yet returned and thus empty array will be passed. Then when the control is passed to the route handler promise2 is logged. Get Payment Response is logged later once paypal.payment.get returns.

To avoid this, the execution sequence can be controlled with the help of promises. Please try with the below code.

async function func(req, res) {
    try {
        const email_id = req.body.email_id;
        const sql_get_orderid =
            "Select payment_id from paypal.execute_order where email_id=?";

        const data = await db.query(sql_get_orderid, [email_id]);

        if (!data.length)
            return;

        console.log('data not 000000');
        const getPaymentPromises = data.map(x => new Promise((resolve, reject) => {
            console.log("data not 1111111");

            paypal.payment.get(x.payment_id, (error, payment) => {
                if (error)
                    return reject(error);

                console.log("Get Payment Response");
                console.log(JSON.stringify(payment));
                resolve(payment);
            });
        }));

        return await Promise.all(getPaymentPromises);
    } catch (error) {
        return { auth: true, message: 'Error on the Server' };
    }
}