在for循环中的回调完成后,如何执行函数? [英] How do I execute a function after the callbacks inside a for loop are completed?

查看:238
本文介绍了在for循环中的回调完成后,如何执行函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在搜索函数中有一个for循环,一个函数执行一个回调,在循环内部执行一个回调,并且我想在循环之后执行一个BUILD()函数,并且在所有回调完成之后。我不知道该怎么做,因为循环在所有回调完成之前完成。回调是API请求,以获取我的数据,我想用这个数据BUILD()。

I have a for loop in a search function, with a function that does a callback that does a callback inside the loop, and I want to execute a BUILD() function after the loop, and after all the callbacks are completed. I am not sure how to do that, because the loop finishes before all the callbacks are done. The callbacks are API requests to get me data, and I want to BUILD() with that data.

我读了延迟,所以我试图把for循环里面的一个函数到deferred,然后调用BUILD()on'.then(...)'。

I read up on deferred, so I tried to put the for loop inside a function to the deferred, and then calling BUILD() on '.then( ... )'. But that doesn't seem to work - I think I am understanding it wrong.

帮助?

注意,这是使用Google Maps Places API(搜索和getDetails)。

Note, this is using the Google Maps Places API (search and getDetails).

var types = {
    'gym' : 'fitness, gym',
    'grocery_or_supermarket': ''
}

function search() {
    for (var key in types) {
         var request = { ... };
         service.search(request, searchCallback);
    }
    // PROBLEM AREA
    BUILD();
}

function searchCallback(results, status) {
    for (var i = 0; i < results.length; i++) {
        var request = { ... };
        service.getDetails(request, detailsCallback);
    }
}

function detailsCallback(place, status) {
    // add place marker to maps and assign info window and info window event
}


推荐答案

var total = 1337; // Some number
var internal_counter = 0;
var fn_callback = function() {
    searchCallback.apply(this, arguments);
    if (++internal_counter === total) {
        BUILD();
    }
};
for (var i=0; i<total; i++) {
    service.search(request, fn_callback);
    ...



说明



首先,我们创建一个本地函数和变量。


  • 变量是一个计数器,

  • 该函数被传递到异步方法( service.search ),它调用原始的回调函数。增加计数器后,检查计数器的值与保存迭代总次数的变量。如果这些都相等,调用整理函数( BUILD )。

  • The variable is a counter, which is increased when the callback is called.
  • The function is passed to the asynchronous method (service.search), which calls the original callback. After increasing the counter, check the value of the counter against the variable which holds the total number of iterations. If these are equal, call the finishing function (BUILD).
var types = { '...' : ' ... ' };

function search() {
    var keys = Object.keys(types);
    var total = keys.length;
    // This counter keeps track of the number of completely finished callbacks
    //  (search_callback has run AND all of its details_callbacks has run)
    var internal_counter = 0;

    for (var i=0; i<total; i++) {
        var request = { '...' : ' ... ' };
        services.search(request, fn_searchCallback);
    }

    // LOCAL Function declaration (which references `internal_counter`)
    function fn_searchCallback(results, status) {
        // Create a local counter for the callbacks
        // I'm showing another way of using a counter: The opposite way
        // Instead of counting the # of finished callbacks, count the number
        //  of *pending* processes. When this counter reaches zero, we're done.
        var local_counter = results.length;
        for (var i=0; i<results.length; i++) {
            service.getDetails(request, fn_detailsCallback);
        }
        // Another LOCAL function (which references `local_counter`)
        function fn_detailsCallback(result, status) {

            // Run the function logic of detailsCallback (from the question)
            // " ... add place marker to maps and assign info window ... "

            // Reduce the counter of pending detailsCallback calls.
            //   If it's zero, all detailsCallbacks has run.
            if (--local_counter === 0) {
                // Increase the "completely finished" counter
                //  and check if we're finished.
                if (++internal_counter === total) {
                    BUILD();
                }
            }
        } // end of fn_detailsCallback
    } // end of fn_searchCallback
}

函数逻辑在注释中解释。我将此部分的标题前缀为复杂,因为该函数使用嵌套的局部函数和变量。视觉说明:

The function logic is explained in the comments. I prefixed the heading of this section with "Complex", because the function makes use of nested local functions and variables. A visual explanation:

var types, BUILD;
function search
    var keys, total, internal_counter, fn_searchCallback;
    function fn_searchCallback
        var result, status; // Declared in the formal arguments
        var local_counter, i, fn_detailsCallback;
        function fn_detailsCallback
            var result, status; // Declared in the formal arguments

在上图中,每个缩进级别意味着一个新的范围在MDN上的探索

当一个函数被调用,例如42次,然后创建42个新的本地作用域,它们共享相同的父作用域。在范围内, 声明的变量< a>对父作用域不可见。虽然父范围中的变量可以通过子范围中的变量读取和更新,但您不声明具有相同名称的变量。这个功能在我的答案的函数中使用。

In the previous picture, each indention level means a new scope Explanaation on MDN.
When a function is called, say, 42 times, then 42 new local scopes are created, which share the same parent scope. Within a scope, declared variables are not visible to the parent scope. Though variables in the parent scope can be read and updated by variables in the "child" scope, provided that you don't declare a variable with the same name. This feature is used in my answer's function.

这篇关于在for循环中的回调完成后,如何执行函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆