Получение значения от анонимной функции & onreadystatechange

StackOverflow https://stackoverflow.com/questions/3579503

Вопрос

У меня есть функция, из которой я хотел бы вернуть значение как серию событий, когда нажата кнопка. Тем не менее, я не могу выяснить, как получить значение от OnReadyStateChange. Как я могу сделать это, чтобы я мог вернуться vicArray[vicID]?

function selectVictim()
{
var vicString;
var vicArray;
var vicID;

var params = "url=queenofsheep.com/Sheep/victims.php";
var request = new ajaxRequest();

request.open("POST", "victims.php", true);
request.setRequestHeader("Content-Type",
                             "application/x-www-form-urlencoded");
request.setRequestHeader("Content-Length", params.length);
request.setRequestHeader("Connection", "close");

request.send(params);

request.onreadystatechange = function ()
{
    if (this.readyState == 4)
    {
        if (this.status == 200)
        {
            if (this.responseText != null )
            {
                vicString = this.responseText;
                vicArray = JSON.parse(vicString);
                vicID = Math.floor(Math.random() * (vicArray.length - 1));
            }
            else alert("Ajax error: No data received");
        }
        else alert("Ajax Error: " + this.statusText);
    }
}
alert(vicArray[vicID]);
}
Это было полезно?

Решение

Вы не можете. Твой onreadystatechange Обработчик вызывается долго после то selectVictim Функция возврата.

То, что у вас вот, так сказать, «асинхронные функции» - то есть функции, которые генерируют свое возвращаемое значение не сразу, но после определенного асинхронного процесса.

Чтобы справиться с этим, нужно использовать обратный вызов, чтобы предоставить возвращаемое значение:

function selectVictim( callback )
{
    ...
    ...

    request.onreadystatechange = function() {
        ...
        vicArray[vicID] = ...;
        callback( vicArray[vicID] );
    }
}

Обратите внимание callback аргумент Тот, кто называет эту функцию, должен предоставить другую функцию для этого аргумента. Затем обратите внимание, как selectVictim Вызывает обратный вызов, когда возвращаемое значение готово.

Теперь, куда бы вы ни звонили selectVictim, Вы должны изменить свой код из:

function someFunc()
{
    doSomething();

    var vic = selectVictim();

    domeSomethingElseWithVictim( vic );
}

К:

function someFunc()
{
    doSomething();

    selectVictim( function( vic ) {

        domeSomethingElseWithVictim( vic );

    } );
}

Достаточно просто?

Другие советы

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

Добавлять callback как параметр:

function selectVictim(callback)

а потом:

vicString = this.responseText;
vicArray = JSON.parse(vicString);
vicID = Math.floor(Math.random() * (vicArray.length - 1));
if (callback) {
 callback(vicID);
}

Когда вы вызываете функцию, вы можете сделать это:

selectVictim(function(vicID){ 
  console.log('This is the id: ', vicID); 
});

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top