【问题标题】:Is Redis "Promiseable" in node?Redis 在节点中是“有前途的”吗?
【发布时间】:2019-02-03 17:00:58
【问题描述】:

似乎和我使用的其他数据仓库不同,我在Redis中不能使用如下策略:

  export class CollectPromises {
       private cachePromises: Array<Promise<any>> = [];

        public addPromise(promise: Promise<any>): void {
           this.cachePromises.push(promise);
        };

        public async executeAllPromises(): Promise<void> {
            await Promise.all(this.cachePromises);
        };
    };

我在 Redis 中的函数:

    async function addSingleDataToSet(key: string, data: any): Promise<boolean> {
        return new Promise<boolean>((resolve, reject) => {


            RedisManager.redisClient.sadd([key].concat(data), ((err, res: number) => {
                if(err) {
                    reject(err);
                } else {
                    resolve(res == 1);
                }
            }));
        });
    };

    async function usingRedis(x, y): Promise<void> {
        await addSingleDataToSet(x, y);
    }

以及在 executeAllPromises() 之前不应该触发任何东西的实际代码(据我了解以及在其他存储库中发生的情况)

CollectPromises.addPromise(usingRedis(x, y));
CollectPromises.addPromise(usingRedis(a, b));
CollectPromises.addPromise(usingRedis(c, d));
await CollectPromiser.executeAllPromises();

问题是 CollectPromises.addPromise(usingRedis(x, y)) (与其他相同)在仅使用 Redis 发生的 executeAllPromises() 之前被触发。

我想知道我是做错了什么还是面临一些特定的 Redis/Node 问题。

【问题讨论】:

  • 问题是 CollectPromises.addPromise(usingRedis(x, y)) (与其他人相同)在 executeAllPromises() 之前被触发 - 这是一个问题吗?这就是 Promise.all 的用途。如果它不能满足您的需求,那么您可能不需要它。请澄清什么是理想的行为。 Redis请求应该一个接一个地发出吗?另外,CollectPromises 是一种奇怪的抽象,它不应该存在,这可以用普通的 JS 来完成。没有可承诺或不可承诺的事情。如果那是您的要求,那么您的承诺是正确的。还有承诺的 Redis 包。
  • 该函数在我将它推送到数组时触发,在 await Promise.all 之前
  • 这是意料之中的。你没有解释为什么这是一个问题。

标签: node.js redis promise


【解决方案1】:

Promise 在您创建它们的那一刻开始运行。在您的示例中,无论您是否调用 executeAllPromises,它们都会执行。

您可能会从引入Task 的概念中受益,该概念定义为返回承诺的函数。这样您就可以在需要时启动它们。

为此,您需要将usingRedis 更改为如下所示:

const usingRedis = (x, y) => () => addSingleDataToSet(x, y);

executeAllPromises 需要调整以运行任务:

await Promise.all(this.cachePromises.map(task => task()));

然后在一堆地方重命名 Promise -> Task。

【讨论】:

  • 但这不正是我正在做的吗?有趣的一点是,我使用相同的策略来访问 google 数据存储,并且它按预期工作。
  • 这不是你在做什么,它是在创建承诺之前添加另一个函数调用。我不确定为什么它与谷歌数据存储一起工作,可能在内部它延迟了行动。我也可能完全误解了您要做什么。我还遇到了一些声称使用 Promise 的库,但实际上使用的是自己滚动的实现,在添加 .then 处理程序之前不会触发。谷歌数据存储是原生地给你承诺还是你需要承诺?
  • 我答应了,几乎一样。但是我确实同意在创建承诺时会测试承诺的内部参数,这让我认为关键可能是考虑承诺将如何行为的 IO 的存在与否。也许 Redis 客户端看起来不像节点的 IO 操作?我将再次检查我的代码,但就像现在一样,我认为我正在对 Datastore 甚至 MySQL 做同样的事情。我不知道任务。现在学习,谢谢
  • 事实是,promise 是否立即开始运行并不重要,而不是在您对它们调用 Promise.all 之后。由于它们立即运行而发生的“坏事”是什么?另请注意,Task 只是我使用的一个术语,我不确定它是否常见。我也听说过用“Thunk”这个词来描述一个动作的额外功能包装器。如果您想查找更多内容。
  • 嗯,我想就是这样,大卫。只有添加 await 或 Promise.all 时,IO 的存在才会使 Promise 成为一个整体。这对你有意义吗?这个假设解释了我现在看到的所有行为,
猜你喜欢
  • 2016-08-31
  • 2010-10-06
  • 2019-02-15
  • 1970-01-01
  • 2011-07-20
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多