简体   繁体   中英

How to wait in one request till another request finishes the execution of same function in nodeJS

I am using meteor. I have a route defined in iron router as follows,

Router.route('/api/generatereceipt', {where: 'server'}).post(function(req, res, next) {
  console.log("API: generatereceipt invoked.");
  const reqBody = req.body;
  ....
}

I want to generate a receipt one at a time. ie the receipt needs to have a unique number which is incremental in nature.

Right now I'm reading the previously stored receipt number and incrementing it by one. I consider that as the receipt number for currently processing receipt.

However, This works fine as long as the generatereceipt API is not called concurrently by multiple clients. When the API is called simultaneously, the same receipt number is considered for all the concurrently processed receipts.

Therefore I want to make a request check if the same REST API is called by some other client in some other request is under process. If it is in the process then I want to wait till its execution in that request thread finishes.

I'm assuming this uses some kind of database/backend to store receipt ids? If so you should use constraints on your database to ensure that the receipt id is unique. Better yet, why not make the receipt id column an auto increment, then you don't need to check the previous receipt number and increment it yourself, it will be handled by the database layer and it just returned as part of the insert.

If it doesn't need to be auto incrementing, then just consider using a UUID.

I can't think of a single reason why you would want to wait on the execution. It would make your app slow for anyone other than the first request and would not be scalable.

If you really have a legitimate reason to structure it this way and generate the auto-increment yourself, then it would be better to explain in detail why this is the case as it might be there are better solutions then just "blocking" the next in line

There should be no issue with concurrent requests. See the following example:

import { Meteor } from 'meteor/meteor'
import { WebApp } from 'meteor/webapp'
import { HTTP } from 'meteor/http'

// create a simple HTTP route

WebApp.connectHandlers.use('/api/generatereceipt', function (req, res, next) {
   // random 0 - 50ms timeout to simulate response delay
  const randomTimeout = Math.floor(Math.random() * 50)

  // use Meteor's Promise.await to await async in non-async functions
  // --> should prevent troubles with legacy iron-router
  const receipt = Promise.await(getReceipt())
  
  setTimeout(() => {
    res.writeHead(200)
    res.end(String(receipt))
  }, randomTimeout)
})

// increment id and return new value
let receiptId = 0
async function getReceipt () {
  return receiptId++
}



Meteor.startup(function () {
  let testCount = 0
  const url = Meteor.absoluteUrl('/api/generatereceipt')

  // simulate concurrent calls by using a timeout of 0
  function call (id) {
    setTimeout(Meteor.bindEnvironment(() => {
      // simulate calling the /api/generatereceipt route
      const response = HTTP.get(url)
      console.log(id, ' => ', response.content) // should match
    }, 0))
  }

  for (let i = 0; i < 25; i++) {
    call(testCount++)
  }
})

as you can see, the calls will resolve to the incremented ids:

=> Meteor server restarted                    
I20200703-09:59:15.911(2)? 9  =>  9
I20200703-09:59:15.912(2)? 7  =>  7
I20200703-09:59:15.913(2)? 4  =>  4
I20200703-09:59:15.913(2)? 0  =>  0
I20200703-09:59:15.913(2)? 21  =>  21
I20200703-09:59:15.913(2)? 24  =>  24
I20200703-09:59:15.913(2)? 17  =>  17
I20200703-09:59:15.913(2)? 18  =>  18
I20200703-09:59:15.915(2)? 2  =>  2
I20200703-09:59:15.917(2)? 19  =>  19
I20200703-09:59:15.923(2)? 6  =>  6
I20200703-09:59:15.923(2)? 23  =>  23
I20200703-09:59:15.925(2)? 11  =>  11
I20200703-09:59:15.928(2)? 8  =>  8
I20200703-09:59:15.931(2)? 16  =>  16
I20200703-09:59:15.932(2)? 10  =>  10
I20200703-09:59:15.934(2)? 5  =>  5
I20200703-09:59:15.934(2)? 13  =>  13
I20200703-09:59:15.934(2)? 22  =>  22
I20200703-09:59:15.936(2)? 20  =>  20
I20200703-09:59:15.936(2)? 15  =>  15
I20200703-09:59:15.939(2)? 14  =>  14
I20200703-09:59:15.940(2)? 1  =>  1
I20200703-09:59:15.940(2)? 3  =>  3
I20200703-09:59:15.943(2)? 12  =>  12

Use async and await for waiting for completion of one request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM