skip to Main Content

I have a timer & i want every time that the timer return to zero, an Ajax request send to the server and tell me how many coins does the user have and at the same time reduces 1 coin.
It works except the first time that Ajax sends the request to URL
Only for the first time it reduces 2 coins instead of 1 .
I just want to know the reason why this happen

the javascript code:

<script>
        var timeout=false;
        $(document).ready(function () {
            match_timer();
        })
    </script>

    <script>
        function match_timer() {
            var n = 5;
            var tm = setInterval(countDown, 1000);

            function countDown() {
                n--;
                document.getElementById('match-timer').innerHTML=n.toString();
                if (n === 0) {
                    clearInterval(tm);
                    get_question();
                    timeout=true;
                }
                if(timeout===true){
                    timeout=false;
                    match_timer();
                }
            }
        }
    </script>

    <script>
        function get_question() {

            $("#question").empty();
            $.ajax({
                url:'http://127.0.0.1:8000/get_another_question/',
                method: 'POST',
                data:{
                    "_token":"{{csrf_token()}}",
                },
                success:function (data) {


                           document.getElementById('question').innerHTML=data['title'];

                           $("#coin_balance").html(data['newCoinBalance']);


                }
            });
        }
    </script>

inside my laravel controller

 public function getAnotherMatchQuestion()
    {
        $user_id=auth()->user()->id;
        $user=AppModelsUser::find($user_id);
        $coin=$user->coin_balance;
        $coin-=1;
        $user->coin_balance=$coin;
        $user->save();


        $question_id=mt_rand(1,15612);
        $getMatchQuestion=QuizQuestion::find($question_id)->only(['question']);
        $data=['title'          => $getMatchQuestion['question'],
                   'newCoinBalance' => $coin];

        return response()->json($data);

    }

2

Answers


  1. This is happening because Ajax is asynchronous operation, meaning, this would execute in a different thread and rest of the code would continue as normal without waiting for ajax call to finish. Double decrement might also be possible if 2 tabs are opened and request comes from both tabs simultaneously. To overcome this, you can make use of transactions. So your Laravel code would look like below:

    public function getAnotherMatchQuestion(){
      try{
        DB::beginTransaction();
        $user_id =auth()->user()->id;
        $user = AppModelsUser::find($user_id);
        $coin = $user->coin_balance;
        $coin -= 1;
        $user->coin_balance = $coin;
        $user->save();
    
        $question_id = mt_rand(1,15612);
        $getMatchQuestion = QuizQuestion::find($question_id)->only(['question']);
        $data = [
                   'title' => $getMatchQuestion['question'],
                   'newCoinBalance' => $coin
                ];
        DB::commit();
        return response()->json($data);
      }catch(Exception $e){
        DB::rollBack();
        return return response()->json(['error' => $e->getMessage()]);
      }
    }
    

    Note that this would be maintaining consistency of data, meaning number of request made is equal to number of requests served without any data loss.

    Login or Signup to reply.
    1. Doublecheck your network to have only 1 AJAX call at the start
    2. Try logging getAnotherMatchQuestion (e.g. to file) with time so you know that it is called as many times as AJAX proceed.
    3. in function match_timer you redefine n everytime with call and recoursivelly call match_timer. before it proceeds (1 second delay)
    var n = 5;
    
    function match_timer
    
    1. The last: use ajax error for situations when call is not correct.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search