1

我正在尝试重构我的程序。我通过使 AJAX 调用同步来使它工作,但现在我想以正确的方式来做。正在发生的事情是用一个包含标题列表的headline新标题进行实例化。从现有列表中选择一个随机标题,但是,如果列表为空,它会进行 AJAX 调用以获取更多标题。headlinesheadlines.getRandom()

我无法完全理解如何让Headline对象构造函数等待调用完成而不使两个对象相互依赖。就目前而言,标题无法实例化,因为它试图从一个未定义的对象实例化,因为调用尚未成功完成。

我知道回调,但是如何使用回调使一个对象等待另一个对象的 AJAX 调用成功,而不会陷入大量对象乱伦?

headline = new Headline(headlines.getRandom(true));
fillHeadline();

如果您想查看更多内容,这里是上下文中的代码。 https://github.com/raddevon/onion-or-not/blob/true-ajax/js/js.js#L104

4

4 回答 4

4

由于您使用的是 jQuery,我会研究 jQuery 承诺。您可以在http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/http://eng.wealthfront.com/2012/12/jquerydeferred找到不错的介绍-is-most-important-client.html

于 2013-05-21T20:08:01.500 回答
2

除了你已经提到的回调。您可以使用deferred对象和promises. 例如,使用jQuery.Deferred

使用 deferred/promises 而不是回调有几个优点:

  • Promise 可以被链接,在做某事之前可以等待几个 Promise,例如 jQuery.when() 。使用回调有点混乱。
  • 您可以检查承诺的状态,例如在等待实际数据时显示初始默认值。
  • 数据的生产者消费者更容易解耦。Promise 以过程/同步方式返回和传递(就像它们是实际数据一样),这有助于避免执行路径难以遵循的复杂回调链。
于 2013-05-21T20:09:30.363 回答
1

JavaScript 中只有几件事是异步的:

  • 事件监听器
  • setTimeout
  • setInterval

AJAX 在内部使用事件侦听器。

所以你做一些类似的事情:

var xhr = new XMLHTTPRequest();
xhr.addEventlistener('readystatechanged', function () {
    console.log(xhr.responseText);
});

如果您正在使用回调,您的代码可能如下所示:

function do_ajax(url, data, callback) {
    var xhr = new XMLHTTPRequest();
    xhr.open("POST", url);
    xhr.addEventlistener('readystatechanged', function () {
        if (xhr.readyState==4 && xhr.status==200) {
            callback(xhr.responseText);
        }
    });
}

do_ajax("service.php", "foo=bar", function (response) {
    console.log(response);
});

如果您有非常复杂的异步流程,我建议您查看Promises这是 jQuery 对 promises 的看法

您可以执行以下操作:

when(async_process()).then(function (result) {
    return do_something_asynchronous(result); // <-- the result is a promise
}).done(function (result) { // <--  and the resolved value is the input here
    console.log(result);
});

使用 Promises,您的代码可能如下所示:

headlines.getRandom(true).then(function (random_headlines) {
    return new HeadLine(random_headlines);
}).done(headline) {
    console.log("And presto!", headline);
});
于 2013-05-21T20:07:21.020 回答
0

稍微打破 ajax 概念,我会尝试:

...
this.refreshContent = function() {
        // Reloads JSON file
        $.ajax(this.url, {

            async: false,

            success: this.fillFromJSON.bind(this),
...
于 2013-05-21T20:06:38.633 回答