Можно ли передать переменную ссылку или указатель в функцию обратного вызова в JavaScript? - PullRequest
0 голосов
/ 21 июня 2019

Я занимаюсь рефакторингом javascript и у меня много похожих вызовов POST на один и тот же URL-адрес PHP.

Было бы неплохо передать функцию postdata и callback (определенную в JiraChangeStatus) в общую функцию (SendPost).

Я новичок в javascript, и у меня сложилось впечатление, что можно использовать указатель / ссылку, если переменная является свойством объекта.

Также попытался использовать переменную для "xhr" вместо свойства объекта, объявив "xhr" в JiraChangeStatus вместо SendPost, и даже объявив его глобально как проверку работоспособности.

function JiraChangeStatus(index) { 

    var postdata = "&status="+document.getElementById("jiraT"+(index).toString()).value;

    SendPost("changestatus.php",postdata, function(obj) {
        alert("readyState: "+obj.xhr.readyState+"\r\nstatus: "+obj.xhr.status);                            
    });                                                  
}

function SendPost(module,postdata,fn)
{
    var obj = {xhr: new XMLHttpRequest()}
    var issuekey = GetJson(document.getElementById("issue").value,'key');                                              
    obj.xhr.open("POST", "modules/jira/"+module, true);
    obj.xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    obj.xhr.onreadystatechange = fn(obj);
    obj.xhr.send("username=user&issuekey="+issuekey+postdata);  
}

Когда выполняется функция обратного вызова, я всегда вижу состояние готовности 1 и состояние 0. Я ожидаю увидеть 4 и 200.

Похоже, javascript передает копию объекта xhr обратному вызову, а не реальному объекту.

Эти функции работают при объединении. Если свойства "xhr" не установлены в области функции обратного вызова для "xhr", обратный вызов не получает значение.

Пожалуйста, дайте мне знать, что я делаю неправильно.

1 Ответ

0 голосов
/ 22 июня 2019

Благодаря Пинти и Берги.

Когда дело дошло до решения моей пользовательской истории, с кодом было 2 проблемы.

Во-первых, когда я использовал obj.xhr.onreadystatechange = fn (obj), он мгновенно вычислял fn. Эта мгновенная оценка вызвала «this», чтобы щелчок мыши был триггером события, а не onreadystatechange.

Вторым было резервирование. Не было необходимости передавать xhr в качестве параметра, когда «this» ссылается на xhr.

Этот код не работает (нерелевантные строки опущены):

function JiraChangeStatus(index) { 
    SendPost("changestatus.php",postdata, function(pass) {
        console.log("This:\r\n"+this); //This: [object Window]                                 
    });                                                  
}
function SendPost(module,postdata,fn) {  
    var xhr = new XMLHttpRequest();     
    xhr.onreadystatechange = fn();       
}

Этот код работает нормально (нерелевантные строки опущены):

function JiraChangeStatus(index) { 
    SendPost("changestatus.php",postdata, function(pass) {
        console.log("This:\r\n"+this); //This: [object XMLHttpRequest]                                 
    });                                                  
}
function SendPost(module,postdata,fn) {  
    var xhr = new XMLHttpRequest();     
    xhr.onreadystatechange = fn;   //no parentheses here fixed my use case    
}

Поэтому я бы принял комментарии Пойнти и Берги, поскольку они решили мой вариант использования.

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

Ответ на мой вопрос о том, как передать ссылку на обратный вызов, когда скобки приводят к немедленной оценке, был здесь: Как передать параметр в функцию, если она не запущена сразу?

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

Поскольку JavaScript позволяет назначать объекты по ссылке, а "xhr" - это объект, как сказал Берги, мне не понадобится обертка для объектов (нерелевантные строки опущены):

function SendPost(module,postdata,fn)
{         
    var xhr = new XMLHttpRequest();      
    xhr.onreadystatechange = fn(xhr); //immediately evaluates fn
}
function JiraChangeStatus(index) { 
    SendPost("changestatus.php",postdata, function(pass) {
        //the result of immediate evaluation is a function 
        //with the parameter "pass" in its scope
        return function() {
            console.log("This:\r\n"+this); //This: [object XMLHttpRequest]
            console.log(this.responseText); //returns the expected response text                
            console.log("Passed Reference:\r\n"+pass); //Passed Parameter: [object XMLHttpRequest]
            console.log(pass.responseText);
            //Both of these stop future callbacks
            //this.abort();
            //pass.abort();
        }
    });                                                  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...