【问题标题】:How would one do async JavaScript setters?如何做异步 JavaScript 设置器?
【发布时间】:2019-09-18 07:39:32
【问题描述】:

我正在尝试使用 async/await 关键字进行异步设置器。

这里有一些需要时间的伪造数据库函数

function getProjectFromDatabase() {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve('My cool project!'), 500) // 500ms latency
    });
}

function setProjectToDatabase(projectName) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve('set!'), 500) // 500ms latency
    });
}


这是用户的实现示例

let user = {

    // Getter
    get project() {
        return (async () => {
            return await getProjectFromDatabase();
        })();
    },

    // Setter
    set project(projectName) {
        return (async () => {
            return await setProjectToDatabase(projectName);
        })();
    },

    // Method 
    setProject(projectName) {
        return (async () => {
            return await setProjectToDatabase(projectName);
        })();
    }
};


这是一个使用示例

(async function() {
    console.log(await user.project); // Getter works!
    await user.setProject('My new cool project!'); // Method works!
    await (user.project = 'Another project'); // Setter doesn't work...
})();


但是 setter 函数的返回值似乎被忽略了。

我怎么能这样做?

【问题讨论】:

  • 似乎这些不适合 getter/setter 属性。
  • return (async () => { return await X; })(); 是写return Promise.resolve( X ); 的一种非常复杂的方式(或者当X 已经是Promise 时只是return X;)。

标签: javascript ecmascript-6 promise async-await


【解决方案1】:

赋值表达式总是在它的右边求值。

  a.b.c = "This is what it gets evaluated to"

没有办法改变它。

【讨论】:

  • 有办法解决这个问题吗?
【解决方案2】:

通常一个setter 设置一些值,你不关心返回值。在传统对象中,这将是一些其他属性(可能不打算直接使用)。转换成数据库之类的东西后,setter 会发布 INSERT 或 UPDATE 并设置新值。

您在 setter 中的代码实际上并没有 设置 任何东西。如果这是一个实际的 DB 调用,您将在数据库中保存一些值,然后对 getter 的下一次调用将产生新值。如果您在 fan DB 调用中添加这样的内容,您将获得更接近传统 getter/setter 逻辑的内容:

const a_user = {project: 'My cool project!'} // some fake db object

function getProjectFromDatabase() {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(a_user.project), 500) // 500ms latency
    });
}

function setProjectToDatabase(projectName) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            a_user.project = projectName // actually set something
            resolve(a_user.project)      // caller of setter doesn't care about return value, but we still need to resolve so async works.
        }, 500) // 500ms latency
    });
}
let user = {

    // Getter
    get project() {
        return (async () => {
            return await getProjectFromDatabase();
        })();
    },
    // Setter
    set project(projectName) {
        return (async () => {
            return await setProjectToDatabase(projectName);
        })();
    },

};

(async function() {
    console.log(await user.project); // Getter works!
    await (user.project = 'Another project'); // 
    console.log(await user.project); // new value has been set
})();

【讨论】:

  • 感谢您的澄清。但是,setter 仍然不起作用(它不是异步的):await (user.project = 'Another project'); console.log(a_user.project); 显示“我的酷项目!”并且不等待承诺的结束
  • @Sharkou 也许我误解了你想要做什么。如果您运行 sn-p,上面代码的输出显示了在用户上设置属性的结果,这是异步发生的。 getter 和 setter 都是异步的。所以你也需要在 console.log 中等待。
猜你喜欢
  • 2015-05-01
  • 2018-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 2013-05-09
  • 2017-02-12
  • 2022-06-14
相关资源
最近更新 更多