在分配正确的值之前,函数不会等待分配响应

时间:2016-04-09 09:14:52

标签: javascript xmlhttprequest

我在ext js.file上有一个xhr函数,它将值发送到休息服务并期望回复。 我在点击事件btn上调用此函数。它第一次响应“未定义”,然后当我再次触发按钮时,它会以正确的值响应。我几乎可以肯定我的反应不是即时的,但为什么函数不能等到它有值然后将它指向我的返回值,而不是发送给我未定义。

var b;

function Transport(parameters, Page) {

    var http = new XMLHttpRequest();

    http.open("POST", "http://***.***.***.***/" + Page, true);

    //Send the proper header information along with the request
    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    http.setRequestHeader("Content-length", parameters.length);

    http.onreadystatechange = function() { //Call a function when the state   changes.
        if (http.readyState == 4 && http.status == 200) {

            b = http.response;
        }
    }
    http.send(parameters);
    return b;
}

页面上函数的调用

var transaction = Transport(parameters,"/mypage.php");
alert(transaction);

3 个答案:

答案 0 :(得分:3)

您正在发出异步请求,但尝试同步处理结果。相反,请使用回调。

function transport(parameters, Page, callback) { // not a constructor, cammel case
    var xhr = new XMLHttpRequest();

    xhr.open("POST", "http://***.***.***.***/" + Page);

    //Send the proper header information along with the request
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    // don't set content-length, you'll get a warning

    xhr.addEventListener('load', function () {
        callback(this.response, this);
    });
    xhr.send(parameters);
    return xhr;
}

然后

transport(
    parameters,
    "/mypage.php",
    function (response) {alert(response);}
);

在ES6中,我们可以将其写为Promise

/**
 * Fetches a resource using XMLHttpRequest and a Promise
 * @param {String} url - The URL of the resource to get
 * @param {String|FormData|Blob|File} [postData] - Any data to POST
 * @param {String} [responseType] - The type of response to expect (defaults to document)
 * @returns {Promise}
 */
function fetch(url, postData, responseType) {
    return new Promise((res, rej) => {
        var x = new XMLHttpRequest();
        x.responseType = responseType || 'document';
        x.addEventListener('load', e => res(x.response, x));
        x.addEventListener('error', e => {
            console.warn('XHR Error', url, e);
            rej(x.response, x);
        });
        if (!postData) {
            x.open('GET', url);
            x.send();
        } else {
            x.open('POST', url);
            if ('string' === typeof postData)
                x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            x.send(postData);
        }
    });
}

然后

fetch(Page, parameters, 'text').then(alert);

答案 1 :(得分:1)

您正尝试在异步模式下使用httprequest。 http.send()立即返回。您可以尝试使用Asynch的代码为False。

var b;
function Transport(parameters,Page) { 
 var http = new XMLHttpRequest();
 http.open("POST", "http://***.***.***.***/"+Page, false);

  //Send the proper header information along with the request
  http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  http.setRequestHeader("Content-length", parameters.length);
  http.send(parameters);
  b=http.response;
  return b;
 }

请参阅http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp了解详情。

答案 2 :(得分:0)

当您致电Transport()发送请求时,b已存在并且值为undefined。该调用是异步的,因此立即返回,而不等待请求完成。该请求仍在后台处理,并在您第二次按下该按钮时完成。完成后,设置b,由第二次调用返回。

如果您将代码更改为以下内容,行为将更像您所期望的那样:

function doSomethingWithMyData(data) {
    ...
}

function Transport(parameters, page) {
    var http = new XMLHttpRequest();

    http.open("POST", "http://***.***.***.***/" + page, true);

    //Send the proper header information along with the request
    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    http.setRequestHeader("Content-length", parameters.length);

    http.onreadystatechange = function() { //Call a function when the state   changes.
        function() {
            if(http.readyState == 4 && http.status == 200) {
                doSomethingWithMyData(http.reponse);
            }
        }
    }
    http.send(parameters);
}

...

var transaction = Transport(parameters,"/mypage.php");