打印前,控制台不会等待文件加载

时间:2016-01-05 23:43:23

标签: javascript json cordova

我有一个包含我想要阅读的JSON数据的文件。我在neontribe.co.uk找到了一些读取文件的代码,但我似乎无法让控制台等待负载完成。

-Xlint:private-shadow

当我运行它时,我在控制台中得到了这个输出:

在function1内部 数据!未定义 数据字符串!未定义 1452034357845.json 内部加载[对象对象]

所以它看起来像some_function然后打印内部函数1.但是它不等待函数从加载传递结果。它会立即从回调函数中打印出两行。然后打印文件名(在循环结束时),然后最终从加载函数中打印控制台消息。看起来我根据控制台返回一个对象,因此数据不应该是未定义的。

1 个答案:

答案 0 :(得分:3)

代码有一些错误,主要是因为它没有考虑异步调用而只是假设一切都以同步方式发生。

callback(data)中的some_function(callback)实际上是在您致电var data = readFromFile(entries[i].name);后调用的。但这里出现了两个问题。

  1. function readFromFile(fileName)不返回任何数据(实际上,它根本不返回任何内容);
  2. reader.readAsText(file);被异步处理。简而言之,这意味着您的代码将继续运行(在您的情况下打印这些消息)并在数据完全加载后调用reader.onloadend回调 - 这对您来说太晚了,因为您的消息已经打印
  3. 有几种方法可以修复此代码,一种好方法是使用Promises。我个人赞成Bluebird。 使用promises,解决方案看起来像这样(伪代码):

    function readFromFile(fileName) {
       return new Promise(resolve, reject) {
           var pathToFile = cordova.file.externalDataDirectory + fileName;
           window.resolveLocalFileSystemURL(pathToFile, function (fileEntry) {
               fileEntry.file(function (file) {
                   var reader = new FileReader();
    
                    reader.onloadend = function (e) {
                        console.log("Share the results... " + JSON.parse(this.result));
                        resolve(JSON.parse(this.result));
                    };
    
                    reader.readAsText(file);
                }, errorHandler.bind(null, fileName));
            }, errorHandler.bind(null, fileName));
        } // Return the promise
    }
    
    function some_function(callback) {
        console.log("inside function1"); 
        var promise = readFromFile(entries[i].name);
    
        promise.then(callback); // Will be called when promise is resolved
    }
    
    some_function(console.log);
    

    Promises允许您在概念上返回一个“契约”,即获取该值,并且一旦收到数据并且承诺得到解决,将会调用等待该值(.then)的所有函数(您可以拒绝)一个承诺,如果它也失败了)。 (抱歉这个错误的解释,但是互联网上有很多关于它的更好的文档,我建议看看它。)

    我希望它有所帮助,还有其他方法来解决这个问题,我相信,如果没有进入发电机,承诺可能是最优雅的。