【问题标题】:How do i save the js filereader result into a variable for futher use?如何将 js 文件读取器结果保存到变量中以供进一步使用?
【发布时间】:2023-04-03 23:10:02
【问题描述】:

我正在尝试将本地 .json 文件上传到我的 Web 应用程序中。我已经到了可以在开发工具中显示该文件的地步,但我无法使其可供进一步使用。我怀疑问题出在我处理(或不处理)文件读取器的异步行为的方式上。

所有东西都在 Angularjs (1.7) 环境中工作,因此是 sn-p 的语法。预期用途是在 openlayers 地图上显示读取的数据。

    this.jsonSelected = function(newFile) {
        let reader = new FileReader();
        let result = 'empty';
        reader.readAsText(newFile);
        reader.onload = function(e) {
            result = e.target.result;
            console.log('in onload', result);
            this.result = e.target.result;
        };
        console.log(this.result);
    };

    this.test = function() {
        console.log(this.file);
    }

我希望代码会注销文件内容两次。一旦打开“console.log('in onload',结果);”又一次在“console.log(this.result);”上。第一个按预期工作。但由于某种原因,第二个不会。控制台中的顺序也颠倒了,console.log(this.result)位于加载日志之前,如您在此screenshot of the console 中所见。

我尝试了几种变体,翻转了名称,更改了 this。等等,但无济于事。这就是为什么我认为我搞砸了异步数据的处理。此外,屏幕截图,更具体地说是日志中的线条,表明存在某种时间问题。

【问题讨论】:

  • 如果应用是客户端应用,很抱歉,您的浏览器将无法在本地保存。
  • 我不想在本地保存数据,恰恰相反。 .json 文件是本地的,我想让它的内容可供浏览器使用。
  • 控制台顺序与预期一致。设置 onload 函数不会使代码等待加载完成,它会继续并记录为空。一段时间后,加载将完成,onload 函数将运行。就像 xhr 等其他异步操作一样,在结果加载之前尝试使用结果是没有意义的,所以对它的所有处理都应该从 onload 函数中调用。与 xhr 一样,在开始读取之前设置 onload 也是一种很好的做法,以避免在加载比预期更快完成时不会调用 onload。

标签: javascript angularjs file gis openlayers


【解决方案1】:

经过一些进一步的研究和反复试验,我得到了解决办法。代码现在看起来像这样:

function readFile(newFile) {
    return $q(function(resolve, reject) {
        let reader = new FileReader();
        reader.onload = function(event) {
            resolve(event.target.result);
        };
        reader.onerror = function(event) {
            reject(event);
        };
        reader.readAsText(newFile);
    });
}

this.jsonSelected = function(newFile) {
    readFile(newFile).then(function(data) {
        console.log(data);
        set$scopeFile(data);
    }, function(errData) {

    });
};

谢谢 Ben,你让我走上了正确的道路,我非常专注于寻找处理异步部分的方法,我只是忽略了范围界定问题。如果有人有一些关于异步 JS 的“傻瓜式证明”文档,我将不胜感激,因为我无法围绕这个主题展开思考。

我使用 angularjs 内置的 $q 服务将整个阅读过程包装成 promise。然后可以通过.then链接。

【讨论】:

    【解决方案2】:

    这是一个经典的异步 + 范围问题...

    首先你使用了错误的范围。 reader.onload 中的 thisthis 中的 console.log(this.result); 不同。
    您应该bind onload 或使用箭头函数。

    接下来,onload 是异步的,因此它将在 console.log(this.result); 之后运行。
    处理这个问题的一种方法是使用 Promises(AngularJS 中的$q)。 比如:

    const deferred = $q.defer(); 
    deferred.then((data) => { console.log('result', data); });
    reader.onload = function(e) {
         result = e.target.result;
         console.log('in onload', result);
         deferred.promise.resolve(e.target.result);
    };
    

    【讨论】:

    • 感谢您的快速回答。不幸的是,我仍然无法使事情正常进行。我使用了您的代码,但控制台抛出错误:Uncaught TypeError: deferred.then is not a function
    • 试试deferred.promise.then
    猜你喜欢
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    相关资源
    最近更新 更多