如何实现getter-function(使用回调)

时间:2010-09-09 16:15:21

标签: javascript callback xmlhttprequest return-value getter

我必须从MySQL数据库(基于用户ID)请求JS脚本的数据。

我没有找到JavaScript的简单解决方案,也无法使用ajax加载数据,因为数据库在不同的域下可用。

我使用PHP和curl实现了一种解决方法 现在JS必须“等待”请求完成,但脚本当然是异步运行而不等待响应。
我知道在JS中等待是不可能的,但必须能够像这样返回值。

我也尝试使用return作为另一个回调,但当然不起作用,因为getter-function无论如何都会进一步运行。

如何实现一个简单的getter,它“等待”并返回来自HTTP请求的响应?

感谢任何其他线索。我现在真的迷路了。
这是源代码的摘录:

/**
 * Simple getter which requests external data
 */
function simple_getter() {

    // http request using a php script, because ajax won't work crossdomain
    // this request takes some time. function finished before request is done.

    /* Example */
    var url = "http://example-url.com/get_data.php?uid=1234";
    var response_callback = handle_result_response;

    var value = send_request( url, response_callback );

    value = value.split('*')[0];

    if (value === '' || value == const_pref_none) {
        return false;
    }

    /* 1. returns undefinied, because value is not yet set.
       2. this as a callback makes no sense, because this function
          will run asynchronous anyway. */
    return value;
}

有关使用功能的其他信息:

/**
 * Callback for the send_request function.
 * basically returns only the responseText (string)
 */
function handle_result_response(req) {
    // do something more, but basically:
    return req.responseText;
}

/**
 * Requests data from a database (different domain) via a PHP script
 */
function send_request( url, response_callback ) {
    var req = createXMLHTTPObject();

    if (!req)
        return;

    var method = (postData) ? "POST" : "GET";

    req.open(method, url, true);
    req.setRequestHeader('User-Agent','XMLHTTP/1.0');

    // More not relevant source code
    // ...

    req.onreadystatechange = function () {
        // More not relevant source code
        // ...

        response_callback(req);
    }

    if (req.readyState == 4)
        return;

    req.send(postData);

}

不是真正相关的代码,但HTTP请求需要:

var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];


function createXMLHTTPObject() {
    var xmlhttp = false;

    for (var i=0; i<XMLHttpFactories.length; i++) {

        try {
            xmlhttp = XMLHttpFactories[i]();
        } catch (e) {
            continue;
        }

        break;
    }

    return xmlhttp;
}

3 个答案:

答案 0 :(得分:3)

你真的,真的不应该尝试同步等待网络请求完成。请求可能永远不会完成,可能会挂起并花费很长时间,等等。由于JavaScript是单线程的,实际上所有主要的浏览器引擎都是单线程的,这会导致整个页面在等待请求时挂起,在某些浏览器中,可能会导致整个浏览器挂起。

你应该做的是替换这样的代码:

var returned = some_request('http://example.com/query');
do_something_with(returned);

代码如下:

some_request('http://example.com/query', function (returned) {
  do_something_with(returned);
});

这样,您永远不会让您的页面或浏览器等待请求,并且只要响应进来就可以完成工作。

答案 1 :(得分:0)

我一般都没看到你的代码有什么问题。

发出请求时,请提供回叫。当响应返回时(您可以轻松检测到),执行回调并将结果传递给它。

答案 2 :(得分:0)

这是客户端应用程序的工作方式。
它不是程序性的,而是按事件工作。

  1. 您将屏幕显示给用户并等待
  2. 用户进行操作
  3. 您呼叫服务器,设置回叫并等待
  4. 响应来了,你执行回调并等待另一个步骤2
  5. 而不是试图改变它,你需要适应它,否则将是一个痛苦的经历。

    Javascript不是多线程的。这意味着一次运行一个语句。真正的异步来自服务器响应和调用回调所花费的时间。你永远不会知道哪个电话会先出现,并且需要考虑到这一点来构建你的程序。