在我提出这个问题之前,我决不是一个流利的javascript开发人员。我来自OOP背景,所以整个异步调用/传递方法很奇怪。
无论如何,我使用了dropbox.js SDK,特别是以下方法(如文档中所述):
(XMLHttpRequest) findByName(path, namePattern, options, callback)
我有一个列表我正在循环查找文件扩展名,并为每个文件扩展名调用findByName
。
var file_extensions = [".py", ".cpp", ".erl"];
function look_for_files(directory_path, file_extensions){
// To hold counts for each file extension
var count_dict = [];
for (var i = 0; i < file_extensions.length; i++){
var current_file = file_extensions[i];
client.findByName(PATH, current_file, function(error, count){
if(error){
return showError(error);
}
else {
count_dict.push(count.length);
}
});
}
console.log(count_dict);
};
正如您所看到的,我每次只是尝试调用该方法并将其返回到名为count_dict
的列表中。但是,我似乎无法将此值推入findByName method.
中的列表中我确定这是因为我误解了回调以及这一切是如何运作的,但有人可能会请求帮助吗?
谢谢
答案 0 :(得分:0)
运行此代码可以帮助您查看问题:
function do_one_thing(thing, callback) {
// Invoke the callback one second later (simulating an async network call)
window.setTimeout(function () {
callback('Done with ' + thing)
}, 1000);
}
function do_things(things) {
for (var i = 0; i < things.length; i++) {
do_one_thing(things[i], function (result) {
console.log('Got result: ' + result);
});
}
console.log('Outside of loop.');
}
do_things(["one", "two", "three"]);
输出应该是这样的:
Outside of loop.
Got result: Done with one
Got result: Done with two
Got result: Done with three
回到你的代码,你开始打三个网络电话,然后打印你的空列表,然后网络电话就完成了。
有几种方法可以解决这个问题。我最喜欢的是使用像Q这样的承诺库:
function do_one_thing(thing) {
var deferred = Q.defer();
// Resolve the promise one second later (simulating an async network call)
window.setTimeout(function () {
deferred.resolve('Done with ' + thing);
}, 1000);
return deferred.promise;
}
function do_things(things) {
return Q.all(things.map(do_one_thing));
}
do_things(["one", "two", "three"]).then(function (results) {
console.log('All done!');
console.log(results);
});
这样所有的调用都可以同时运行,但只有在所有调用完成后才能获得结果。
另一种选择是推出自己的机制来等待事情的完成:
function do_one_thing(thing, callback) {
// Invoke the callback one second later (simulating an async network call)
window.setTimeout(function () {
callback('Done with ' + thing);
}, 1000);
}
function do_things(things, callback) {
var results = [];
var pending = things.length;
for (var i = 0; i < things.length; i++) {
// "index" just captures the current value of "i"
(function (index) {
do_one_thing(things[index], function (result) {
// Store the results in the right place.
results[index] = result;
// Decrement the pending count.
pending -= 1;
// If we're all done, invoke the callback with the full results.
if (pending === 0) {
callback(results);
}
});
})(i);
}
}
do_things(["one", "two", "three"], function (results) {
console.log('All done!');
console.log(results);
});
最重要的是,由于每个调用都是异步的,并且它们可能以任何顺序返回,您需要某种方式等待它们全部完成,然后提供表单中调用代码的答案回调。
答案 1 :(得分:0)
client.findByName
是异步的,您的代码不会考虑到这一点。下面的代码通过检查count_dict中的条目数来解决此问题,并等待所有网络调用都返回。
var file_extensions = [".py", ".cpp", ".erl"];
function look_for_files(directory_path, file_extensions){
// To hold counts for each file extension
var count_dict = [];
countExtensions(file_extensions, function(){
console.log(count_dict)
});
function countExtensions (file_extensions, callback) {
for (var i = 0; i < file_extensions.length; i++) {
var current_file = file_extensions[i];
client.findByName(PATH, current_file, function(error, count){
if(error) return showError(error);
count_dict.push(count.length);
if (count_dict.length === file_extensions.length) return callback();
});
}
}
};