从dropbox.js中获取值findByName方法()?

时间:2014-08-22 15:49:53

标签: javascript dropbox-api

在我提出这个问题之前,我决不是一个流利的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.中的列表中我确定这是因为我误解了回调以及这一切是如何运作的,但有人可能会请求帮助吗?

谢谢

2 个答案:

答案 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();
      });
    }    
  }
};