我在搜索函数中有一个for循环,其函数执行一个回调,在循环内进行回调,我想在循环之后执行一个BUILD()函数,并在完成所有回调之后。我不知道该怎么做,因为循环在所有回调完成之前完成。回调是获取数据的API请求,我想用这些数据构建BUILD()。
我读了deferred,所以我试着把for循环放在一个函数中,然后在' .then(...)'上调用BUILD()。但这似乎不起作用 - 我认为我理解错了。
HELP?!
请注意,这是使用Google Maps Places API(搜索和获取详细信息)。
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
}
答案 0 :(得分:3)
只需对代码进行少量修改即可实现。
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
)。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
}
功能逻辑在注释中说明。我将此部分的标题添加为“复杂”,因为该函数使用了嵌套的本地函数和变量。一个直观的解释:
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
在上图中,每个缩进级别表示新的scope Explanaation on MDN 当一个函数被调用时,比如42次,那么就创建了42个新的本地作用域,它们共享相同的父作用域。在范围内,父范围不可见declared variables。虽然父作用域中的变量可以通过“子”作用域中的变量读取和更新,但提供了,您没有声明具有相同名称的变量。此功能用于我的答案功能。
答案 1 :(得分:0)
我认为你已经理解了这一点,但是当前一个回调函数仍在运行时,它会被线性调用。这就像你创造了额外的线程。解决问题的一种方法是使用搜索函数使用for循环对BUILD进行回调。这可以保证在调用之前完成所有功能。
此问题可能有助于实现回调:Create a custom callback in JavaScript