panji gemilang
panji gemilang

Reputation: 809

Making Express synchronous request and sending multiple data in same one request

I want to make a request multiple data in one request with loop, but as far as I tried it always run Asynchronously (I guess?). I'm using Reactjs Redux and Express.

Here's my code :

profile.jsx

while(i < condition.length) { // say that length = 4
   myData.forEach(item => addingData.push(item))

   // Here I'm calling my request
   this.props.addEmployee(addingData)

   // I wanted to make this 'i' increase ONLY when the request is done.
   // But I'm not sure how to do that
   i++
}

Express Request

router.post("/add-employee", (req, res) => {
    Employee.findOne({ _id: req.id }).then(user => {
       if (user) {

          const newEmp = new Employee({
              nip: req.body.nip,
              name: req.body.name
            })

          // add to employee model. Save employee
            newEmp
              .save()
              .then(user => {
                // Variable for profile
                const newProfile = {}
                newProfile.user = user._id

                // Save profile
                new Profile(newProfile).save()
                console.log("selesai save")

          res.status(200).json(user)
       } else {
          // error
       }
    })
})

this always returns the last data with 4 copies, which means it adding four data and its all same. How do I accomplish this, I read that this is because the request didn't run synchronously but how can I do that?

Thank you for your help!

UPDATE

as suggested by @Nathan Fries, I created a new router to handle the multiple requests with an array of object. But I still got the Synchronous problem (I guess?). Here's my code :

profile.jsx

for (i; i < this.state.file.length; i++) {
      this.state.file[i].map(item => temp.push(item))

      addData.push({
        nip: temp[0],
        name: temp[1]
      })

      temp = []
    }

// make a request
this.props.addMultipleEmployee(addData)

routes/api/employees.js

// create/add multiple karyawan
router.post(
  "/add-multiple-karyawan",
  passport.authenticate("jwt", {
    session: false
  }),
  (req, res) => {
    let errors
    let isValid
    let newEmp
    let i = 0

    // console.log(req.body) 
    // this req.body value : 
    // [{nip: "nip1", name: "name1"}, 
    //  {nip: "nip2", name: "name2"}]

    for (i; i < req.body.length; i++) {
      isValid = validationEmployee(req.body[i]).isValid
      errors = validationEmployee(req.body[i]).errors

      if (!isValid) {
        return res.status(404).json(errors)
      }

      console.log("checking for sure")
      console.log(req.body[i])
      // The value was still there


      Nip.findOne({ nip: req.body[i].nip }).then(profile => {
        if (profile) {
          return res.status(400).json({
            nip: "NIK tidak valid, karena ini adalah NIK admin. Coba lagi"
          })
        } else {

          // But when it's trying to findOne, the error message said
          // 'nip' are undefined
          Karyawan.findOne({
            nip: req.body[i].nip
          }).then(exists => {
            if (exists) {
              return res.status(400).json({
                nip: "Karyawan telah terdaftar dengan NIK yang sama."
              })
            } else {

              // adding request.body to mongoDB
              newEmp = new Karyawan({
                nip: req.body[i].nip,
                name: req.body[i].name
              })

              // add to employee model. Save employee
              newEmp
                .save()
                .then(user => {
                  // Variable for profile
                  const newProfile = {}
                  newProfile.user = user._id

                  // Save profile
                  new Profile(newProfile).save()
                  console.log("selesai save")

                  res.status(201).json(user)
                })
                .catch(err => {
                  console.log(err)
                })
            }
          })
        }
      })
    }
  }
)

and I got this error :

TypeError: Cannot read property 'nip' of undefined
[0]     at D:\Kuliah\Semester-7\ptpnx-jombang\routes\api\employees.js:198:32
[0]     at processTicksAndRejections (internal/process/task_queues.js:85:5)
[0] (node:22236) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[0]     at ServerResponse.setHeader (_http_outgoing.js:464:11)
[0]     at ServerResponse.header (D:\Kuliah\Semester-7\ptpnx-jombang\node_modules\express\lib\response.js:771:10)
[0]     at ServerResponse.send (D:\Kuliah\Semester-7\ptpnx-jombang\node_modules\express\lib\response.js:170:12)
[0]     at ServerResponse.json (D:\Kuliah\Semester-7\ptpnx-jombang\node_modules\express\lib\response.js:267:15)
[0]     at D:\Kuliah\Semester-7\ptpnx-jombang\routes\api\employees.js:247:22
[0]     at processTicksAndRejections (internal/process/task_queues.js:85:5)
[0] (node:22236) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
[0] (node:22236) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process
with a non-zero exit code.

It is said that I need to make it Synchronously with Async/await or Promise? But I'm not sure how to do that. I still a novice with Async/await and Promise.

Thank you for your help!!

Upvotes: 2

Views: 429

Answers (1)

Nathan Fries
Nathan Fries

Reputation: 1524

Why don't you add a /add-employees route for handling of multiple employee additions? You could push them to an array in your jsx, then send them all at once. This avoids the async issue entirely.

You are also declaring newEmp with const instead of let. You can get the length by req.length and iterate through the array.

Upvotes: 1

Related Questions