无法从异步函数

时间:2015-07-25 20:50:57

标签: javascript asynchronous d3.js

我有以下代码,其中d3.json是异步函数。我试图在循环中运行它,而我的count等于100.我的while循环在第一次迭代后停止,因为count发生在异步函数内,所以我不要经常多次运行它。如何获得正确的计数,以便我的while循环在保持异步特征的同时继续执行?

    $(document).ready(function() {
    $('button').click(function() {
        var start = new Date().getTime();
        while(count == 100){
            console.log("first iteration");
            count = 0;
            d3.json("/api/messages/" + offset, function(error, json) {
                if (error) return console.warn(error);
                data = json;
                for(var i = 0; i < data.messages.length; i++){
                    console.log(data.messages[i].date);
                    count++;
                    console.log(count);
                }
            });
            offset += 100;
        }
            var end = new Date().getTime();
            var time = end - start;
            console.log("Time to execute : " + time);
    });
});
编辑:我正在尝试拨打电话,如下所示。在每次通话时,您都会检查并确保返回100项(计数),如果没有,您将停止while循环

  1. /api/messages/0
  2. /api/messages/100
  3. /api/messages/200
  4. /api/messages/300
  5. /api/messages/400
  6. /api/messages/500
  7. /api/messages/600

2 个答案:

答案 0 :(得分:2)

我将如何做到这一点:

创建一个接受相关参数的函数:start offset,increment,最重要的是应该在最后执行的done回调。

此函数包含一个worker函数,它将调用API,检查结果并调用自身或done回调:

function fetchAllMessages(start, increment, done) {
    var messages = [];
    (function nextCall(offset) {
        d3.json("/api/messages/" + offset, function (error, data) {
            if (error) return done(error, messages);
            if (!data.messages) return done("unexpected response format", messages);

            messages.push.apply(messages, data.messages);
            if (data.messages.length === increment) {
                nextCall(offset + increment);
            } else {
                done(null, messages);
            }
        });
    })(start);
}

现在您只需从Click事件处理程序中使用它:

$(function() {
    $('button').click(function() {
        var start = Date.now();

        fetchAllMessages(0, 100, function (err, messages) {
            var end = Date.now();
            if (err) console.warn(err);
            console.log(messages);
            console.log("Time to execute : " + (start - end));
        });
    });
});

答案 1 :(得分:1)

我们的想法是将此ajax次调用链接起来,直到达到某个截止点(在此示例中,偏移量大于最大值)。

我已经将d3.json调用更改为jQuery.getJSON以获得此答案,因为它更容易在jsfiddle上调试,但概念完全相同。我还必须更改请求使用jsfiddle debug api的URL。

var start = new Date().getTime();
var offset = 0;
var maxOffset = 600;
var baseUrl = "/echo/json"; // change this to /api/messages in production

var callback = function(json) {
    console.log(json);

    console.log("current offset: " + offset);

    data = json;
    //  ... do something with data ...

    // increment the offset
    offset += 100;

    // don't run any more and return the execution time
    if (offset > maxOffset) {
        var end = new Date().getTime();
        var time = end - start;
        console.log("Time to execute : " + time);
        return; // don't run any more
    }

    // offset too small so run another getJSON call with our callback
    $.getJSON(baseUrl + "?" + offset, callback);
}

// when button is click, start the json call chain
$('button').click(function() {            
    // change the "?" to "/" in production
    $.getJSON(baseUrl + "?" + offset, callback);
});

如果您需要帮助将此问题翻译成您确切的问题,请与我们联系。

Here是jsfiddle。