Как вызвать функцию, связанную с ajax, в цикле в javascript?

#javascript #jquery

#javascript #jquery

Вопрос:

Я запускаю цикл, и внутри цикла я вызываю функцию. Функция выполняет вызов ajax и возвращает ответ, но проблема в том, что цикл не ожидает ответа, поэтому функция возвращает undefined.

 function checkBidStatus(index) {
  $.ajax({
     type:'get',
     url:'/orderbook/checkorderdetails',
     success: function(data){
        $parsedData = JSON.parse(data);
        if($parsedData[index]) {
          return "Hello";
        } else {
          return "Bye";
        }

        //$("#bid-details .modal-dialog").html(data);
     },
    error: function (response) {
      console.log(response);
    }
  });
}

let content = '';
 for(let i = 1; i <= 10; i   ) {
    content  = '<div>'   
    (checkBidStatus(i))  
    '</div>';
 }
  

Комментарии:

1. Проблема в том, что цикл for является синхронным, но вызов ajax является асинхронным. Т. Е. эта функция должна ждать ответа сервера. Поэтому вызывающий объект должен использовать обратные вызовы или обещания, прежде чем перейти к следующему запросу.

2. пожалуйста, уточните с помощью кода

3. Ок … выполняется. Скоро появится код.

4. Вы можете сделать вызов ajax синхронным, определив async:false в теле ajax. это простое решение, но оно также блокирует ваш поток пользовательского интерфейса, что означает, что ваш пользовательский интерфейс не будет отвечать во время цикла.

5. @ayan_84 синхронный Ajax устарел из-за плохого пользовательского интерфейса, который он предоставляет. Это блокирует браузер во время использования, и длительный запрос (или серия запросов) может создать у пользователя впечатление, что страница разбилась. Кроме того, поскольку она устарела, вы можете ожидать, что браузеры перестанут поддерживать ее в обозримом будущем. Это не очень хороший способ решить проблему. Связывание обещаний было бы более подходящим решением

Ответ №1:

Проблема в том, что цикл for является синхронным, но вызов ajax является асинхронным. Т. Е. эта функция должна ждать ответа сервера. Поэтому вызывающий объект должен использовать обратные вызовы или обещания, прежде чем перейти к следующему запросу.

Существуют элегантные способы выполнения этой задачи с использованием определенных библиотек, таких как async, но «быстрый VanillaJS» способ решения этой задачи с использованием promises был бы примерно таким:

 const contentTemplate = '<div>[BID_RESULT]</div>';
const nRequests = 10;
var requestCnt = 0;
var content = '';

function checkBidStatus(index) {
    return new Promise((resolve, reject) => {
        $.ajax({
            type:'get',
            url:'/orderbook/checkorderdetails',
            success: function(data){
               $parsedData = JSON.parse(data);
               resolve({ index: index   1, msg: $parsedData ? "Hello" : "Bye" });
            },
            error: reject
        });
        // <-- NOTE: there is no return statement at this line. Hence if 
        // you were to call this function from your for loop, you'd see 
        // undefined
    }
}
  

Затем вы можете продолжать вызывать эту функцию рекурсивно:

 function multipleRequests(){
    checkBidStatus(requestCnt)
    .then((resp) => { // This runs if the promise RESOLVES (i.e., success)
        content = contentTemplate.replace('[BID_RESULT]', resp.msg);
        // --- [then do what you want with content] --- //
        // Request again
        requestCnt  ;
        if( requestCnt < nRequests ){
            multipleRequests();   
        }
    })
    .catch(console.error) // This runs if promise rejects (i.e., has an error)
}

// Run:
multipleRequests();
  

Ответ №2:

Почему бы не использовать обещание внутри и не дождаться этого обещания, чтобы получить требуемый результат, после чего обновить DOM? В вашем методе checkBidStatus вы можете создать обещание и вернуть его. Когда результат ajax будет доступен, разрешите обещание с помощью результата ajax.

Вызывающий метод должен будет дождаться разрешения promise, а затем обновить DOM.

 let content = '';
for(let i = 1; i <= 10; i   ) {
  checkBidStatus(i).then(result => {
    content  = '<div>'  result   '</div>';
  })
}
  

Примечание: Я не тестировал код, но что-то подобное должно работать. Также порядок divs, созданных на основе индекса, не гарантируется, поэтому вам может потребоваться позаботиться об этом, если порядок важен.

Комментарии:

1. Я думаю, что это довольно приятно. Я думаю, что комбинация наших ответов должна заставить его работать 🙂

Ответ №3:

Вы должны ждать ответа от сервера для каждой итерации в цикле.

 function checkBidStatus(index) {
$.ajax({
    type: 'get',
    url: '/orderbook/checkorderdetails',
    success: function(data) {
        $parsedData = JSON.parse(data);
        if ($parsedData[index]) {
            return {
                msg: 'Hello',
                index: index   1,
            };
        } else {
            return {
                msg: 'Bye',
                index: index   1,
            };
        }

        //$("#bid-details .modal-dialog").html(data);
    },
    error: function(response) {
        console.log(response);
    },
});
  

}

 let content = '';
let i = 1;
while (i <= 10) {
    let { msg, index } = checkBidStatus(i);
    content  = '<div>'   msg   '</div>';
    i = index;
}