1

Background

This is the client side Javascript, where I make a post request to update the respective tables with the form parameters. My database has two tables-Rabbit table, and MyStuff table, and MyStuff table holds a foreign key to the rabbit table. Now, I first update the Rabbit table by making a post request which not only updates the Rabbit table but also updates the value of the rabbitID variable in the server, and the second request updates the MyStuff with the respective form parameters, and also makes use of the rabbitID variable just updated.

async function updateAllHelper(formDataParam) {
  let updateR = await updateRabbitTable(formDataParam);
  let updateMyS = await updateMyStable(formDataParam);
}

async function updateRabbitTable(formDataParam) {
  let headers = new Headers();
  const response = await fetch("/updateRtable", {
    method: "POST",
    body: formDataParam,
    headers
  });
  const body = await response.json();
  return body;
}

async function updateMyStable(formDataParam) {
  let headers = new Headers();
  const response = await fetch("/updateMyStable", {
    method: "POST",
    body: formDataParam,
    headers
  });
  const body = await response.json();
  return body;
}

Down below are my endpoints for the server side. In the "updateRtable" endpoint, I update the rabbit table and fetch the maximum rabbit ID and store that value in the lastInsertedRId variable. After that the "updateMyStable" endpoint updates the MyStuff table with the form parameters, and also makes use the lastInsertedRId.

app.post("/updateRtable", (req, res) => {
  console.log("went inside rabbit");
  console.log(req.body.RName);
  let successful = true;
  con.query(`INSERT INTO RABBIT(R_ID, RABBIT_NAME, DATE_OF_BIRTH, RABBIT_STATUS, SEX, BREED) VALUES (NULL, '${req.body.RName}', '${req.body.dob}', '${req.body.rStat}', '${req.body.sex}', '${req.body.breed}')`, function(err, result, fields) {
    if (err) {
      successful = false;
      console.log(err);
    } else {
      //to get rabbitID
      console.log("went inside fetching maximum id");
      con.query(`SELECT max(R_ID) FROM RABBIT`, function(errinside, r, f) {
        if (errinside) {
          successful = false;
          console.log(errinside);
        } else {
          lastInsertedRId = JSON.parse(JSON.stringify(r))[0]['max(R_ID)'];
        }
      });
    }
  });
  if (successful === true) {
    res.status(200).send({
      success: true
    });

  } else {
    res.status(ERROR_STATUS_CODE).send({
      success: false
    });
  }
});

app.post("/updateMyStable", (req, res) => {
  console.log("went inside mystuff table");
  let successful = true;
  con.query(`INSERT INTO MYSTUFF(R_ID, NOTES, Kibble, Carrier, Medication, Treats, Blankets, Toys, Drop_off_Date, Pick_up_Date) VALUES ('${lastInsertedRId}', '${req.body.notes}', '${req.body.kibble}', '${req.body.carrier}', '${req.body.medic}', '${req.body.treats}', '${req.body.blankets}', '${req.body.toys}', '${req.body.dropD}', '${req.body.picKD}')`, function(err, result, fields) {
    if (err) {
      console.log(err);
      successful = false;
    }
  });
  if (successful === true) {
    res.status(200).send({
      success: true
    });
  } else {
    res.status(ERROR_STATUS_CODE).send("Server side error");
  }
});

Goal

Since the MyStuff table holds a foreign key to the Rabbit table, I obviously want to complete the call to the first endpoint completely(updating the table and fetching the latest ID), and to accomplish that goal, I am trying to make use of async/await where I wait for a response from the server side before executing the next endpoint.

Problem

However, the second endpoint is being executed before the completion of the first endpoint. Specifically, I found out that lastInsertedRId is yet to be updated while the "updateMyStable" endpoint is executed.

  • 1
    if(successful===false){ res.status(200).send({ success: true}); }, this code in your first end-point is a typo, it should be if succesfull true then send 200 from response right? – Hrishikesh Kale Jun 12 '21 at 05:40
  • Try using `async: false,` in your ajax call. – Raky Jun 12 '21 at 05:40
  • @Raky No, don't ever recommend that. – Barmar Jun 12 '21 at 05:41
  • 1
    Get out of the habit of writing `=== false` and `=== true`. Just write `if (successful)` or `if (!successful)`. – Barmar Jun 12 '21 at 05:45
  • 1
    The problem is that you're sending the response from the endpoint before the query completes. `con.query()` is asynchronous. – Barmar Jun 12 '21 at 05:46
  • 1
    And that means you're checking the `successful` variable before it has been set in the callback function. – Barmar Jun 12 '21 at 05:46
  • 1
    BTW, you don't need to use another query to get `lastInsertedRid`. It's in `result.insertId`. – Barmar Jun 12 '21 at 05:48
  • 1
    And if you do use a query, you should use `SELECT LAST_INSERT_ID()`. `SELECT MAX(R_ID)` could get an ID that was inserted by another connection after your insert. – Barmar Jun 12 '21 at 05:49
  • 1
    @Barmar Thanks for that fix, I am just going to use that idea to avoid more headaches. – Futuristic Gladiator Jun 12 '21 at 05:56

1 Answers1

1

con.query() is asynchronous. Since it's asynchronous, it only awaits till that line and starts executing other endpoints. That's why your code is out of order.

You'll find a related issue here.

lemon
  • 14,875
  • 6
  • 18
  • 38