как заставить Javascript setTimeout возвращать значение в функции

У меня есть функция, которая вызывает какую-то службу и возвращает ответ. Если ответ FALSE, он ждет 1 секунду, чтобы снова запросить службу (которая затем, вероятно, возвращает TRUE).

Как мне сделать, чтобы вызвать мою функцию "checkService()" один раз и получить реальное значение? (первая или вторая попытка, определяемая функцией) Я устанавливаю значение RET внутри функции, но функции всегда возвращают первый RET, потому что setTimeout асинхронный.

Другими словами, мне нужен какой-то «сонный» трюк или какое-либо решение (может быть и jQuery).

function checkService() {

  //this may return TRUE or FALSE
  var RET = someServiceResponse(); 

  // here waits 1 second, then ask the service again
  if( RET == true ) {
    return true;
  } else {

    setTimeout(
        function() {
            //it must return the second response of the service
            RET = someServiceResponse();  
        }, 
        1000
    );

    // I want the checkService() return the response after de timeout
    return RET;  
  }
}

function alertResponse() {
    alert( checkService() );
}

person Aberel    schedule 04.08.2014    source источник
comment
Получает ли someServiceResponse результат вызова ajax? Это может быть сердцевиной вашей проблемы.   -  person Travis J    schedule 05.08.2014
comment
хотя ожидание в 1 секунду кажется полезным, его легко нарушить, если для возврата вызова требуется больше времени. Я бы рекомендовал разделить эту функциональность с функцией обратного вызова, которая срабатывает, когда ответ фактически доставлен.   -  person Bosworth99    schedule 05.08.2014
comment
Трэвис, нет. Однако я не возражаю, если ожидание занимает более 1 секунды. Это не важно, это время, просто нужно немного подождать (полсекунды или около того) и проверить его снова.   -  person Aberel    schedule 05.08.2014


Ответы (2)


Вы должны использовать функцию обратного вызова, когда ожидаете результата от службы.

Как это :

function checkService(callback) {

    //this may return TRUE or FALSE
    var RET = someServiceResponse();

    // here waits 1 second, then ask the service again
    if( RET == true ) {
        callback(RET);
    } else {

        setTimeout(
                function() {
                    //it must return the second response of the service
                    RET = someServiceResponse();
                    callback(RET);
                },
                1000
        );

        // I want the checkService() return the response after de timeout
        return RET;
    }
}

Поэтому, когда вы хотите вызвать службу, вам просто нужно сделать:

checkService(function(status){
    alert(status);

    // Here some code after the webservice response
});
person Raphaël Malié    schedule 04.08.2014
comment
или снова вызовите checkService() в функции тайм-аута. должно работать в любом случае. - person Rebirth; 05.08.2014
comment
Я использовал alert(), чтобы упростить задачу. На самом деле мне нужно вызывать checkService() из многих других функций в моем коде и делать все необходимое в соответствии с ответом checkService(). Если я снова вызову его извне, я сделаю то же самое, что и checkService(). Это потому, что я сделал функцию checkService(). - person Aberel; 05.08.2014

Погуглив «обратный вызов javascript setTimeout», вот удобный jsFiddle о 3 результатах вниз:

getData('http://fakedomain1234.com/userlist', writeData);

document.getElementById('output').innerHTML += "show this before data ...";

function getData(dataURI, callback) {
    // Normally you would actually connect to a server here.
    // We're just going to simulate a 3-second delay.
    var timer = setTimeout(function () {
        var dataArray = [123, 456, 789, 012, 345, 678];
        callback(dataArray);
    }, 3000);
}

function writeData(myData) {
    console.log(myData);
}

http://jsfiddle.net/cwbuecheler/Y9Ca8/

person elzi    schedule 04.08.2014