【问题标题】:unable to set proper scope for variable within a JavaScript promise无法在 JavaScript 承诺中为变量设置适当的范围
【发布时间】:2018-10-30 13:16:50
【问题描述】:

我遇到了一个奇怪的问题,即在本地范围内创建了一个新变量,即使它是在外部定义的,

从下面的代码

在我调用 buildMeta() 并检查“数据”的内容后,它总是为空 暗示它根本没有被修改,即使我专门针对“that.data”,它指的是类的对象。

如果有人能指出我做错了什么,我将不胜感激。

class meta {

    constructor(files) {
        if(!files) throw Error("files not specified");
        this.data = {};
        this.ls = files;
    }

  buildMeta() {
        var that = this;
        for(let i = 0; i < that.ls.length; i++) {

            mm.parseFile(that.ls[i]).then(x => {
                var info = x.common;
                that.data[info.artist] = "test";
            }).catch((x) => { 
               console.log(x);    
            });
       }

    }
 }
const mm = new meta(indexer); // indexer is an array of file paths
mm.buildMeta();
console.log(mm.data);

【问题讨论】:

    标签: javascript ecmascript-6 scope es6-promise


    【解决方案1】:

    您在这里将同步与异步代码混合在一起。 for 循环不会等待 parseFile 承诺解决。 解析文件时可以使用Promise.all填写数据。

    // Class names should be written using a capital letter 
    class Meta {
        ...
        buildMeta() {
         // You don't need this assignment since you're using arrow functions
        // var that = this;
        const promises = this.ls.map(filePath => mm.parseFile(filePath));
        return Promise.all(promises).then(resolvedPromises => {
            resolvedPromises.map(({ parsedFile }) => {
                this.data[parsedFile.common.artist] = "test";
           });
           return this.data;
        }).catch(console.error);
    }
    
    ...
    
    const mm = new meta(indexer); // indexer is an array of file paths
    mm.buildMeta().then(data => {console.log(data)});
    

    希望这会有所帮助。

    【讨论】:

    • 感谢您的澄清,我现在将尝试学习更多的 Promise 概念。
    【解决方案2】:

    您在parseFile 完成之前记录mm.data。您的代码暗示它返回一个承诺,因此您插入 that.data 将在您的 console.log(mm.data) 执行后发生。

    你需要从buildMeta返回一个promise,这样你才能做到……

    const mm = new meta(indexer);
    mm.buildMeta().then(() => {
        console.log(mm.data);
    })
    

    这是一个buildMeta,应该可以满足您的需求。这将返回一个等待所有 parseFile 调用完成其工作并更新 this.data...

    的承诺
    buildMeta() {
        return Promise.all(this.ls.map(f => mm.parseFile(f).then(x => {
            var info = x.common;
            this.data[info.artist] = "test";
        })))
    }
    

    【讨论】:

    • 似乎不起作用,它的值仍然是 {},pastebin.com/tmH6tCLv Promises 对我来说有点混乱。
    • 我添加了一个 buildMeta 的实现供你尝试。
    猜你喜欢
    • 2018-11-30
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 2014-07-26
    • 2017-09-27
    • 2019-11-05
    • 1970-01-01
    相关资源
    最近更新 更多