【问题标题】:How would I export resolved Promises我将如何导出已解决的 Promise
【发布时间】:2017-07-17 18:12:54
【问题描述】:

我有许多需要导出的结果值的承诺。该值实际上是与嵌入式数据库的连接。

问题是我有几个中间件承诺在解决最终数据库资源之前在连接上工作。我对数据库中的每个集合都执行此操作。

如果我多次使用该方法,我将创建与该数据库的多个连接,其中包含许多自己的中间件副本,这些副本可能会变得相当大。如何将这个 Promise 和所有其他 Promise 导出到一个最终对象中?

我应该创建一个在构造函数中解析承诺并将集合项作为公共变量的单例类吗?或者我应该如何解决将它们导出到一个对象中?

编辑 - 显示示例承诺。众多之一

这只是集合连接之一。请注意,当调用此方法时,它会创建一个new 集合。使用 IndexLoader 为每个集合创建内存中的二叉树。

这就是为什么我希望解决这个方法并将结果作为集合返回到一个要在那里使用的对象中。如果我要在整个应用程序中调用此方法,那么每次都会创建一个新的二叉树。

export const Users = (): Promise<Collection> => {
  return new Promise<Collection>((resolve, reject) => {
      const User: Collection = new Collection("Users");
      const indexPromises: Array<Promise<any>> = [];
      const uniqIndices: string[] = ["username"];

      User.pre("save", setDefaults);
      User.pre("update", updateDefaults);

      uniqIndices.forEach((v) => {
        indexPromises.push(IndexLoader(User, {fieldName: v, unique: true}));
      });

      Promise.all(indexPromises)
          .then(() => {
              resolve(User);
          })
          .catch(reject);
  });
};

编辑 2 - 我所说的单例分辨率导出是什么意思

我觉得这样使用单例是合理的。

import {Users} from "./file"; // this is the method above
export interface IDB {
    Users: Collection;
}
export class DB implements IDB {
    public static getInstance() {
        if (!DB.instance) {
            DB.instance = new DB();
        }
        return DB.instance;
    }
    private static instance: DB;
    public Users: Collection;
    
    constructor() {
        Users()
          .then((res) => {
              this.Users = res;
          })
          .catch(/** error handler */);
     }
}

使用其他文件中的类与相同的连接和二叉树进行交互

import {DB} from "..";
let db = DB.getInstance();
db.Users.insert({/** new object */})
    .then()
    .catch()

!!单例试过了,不行!!

【问题讨论】:

  • “如果我多次使用该方法……” - 你有没有一个承诺,或者你有一个返回承诺的函数(“方法”)?发布您的代码(可能是无承诺的或无效的)会有很大帮助。
  • "我有许多承诺,我需要导出结果值。" - 你不能(异步)导出该值。但你可以为它导出承诺!
  • "我应该创建一个在构造函数中解析承诺的单例类" - 不,absolutely don't do that
  • 关于示例代码,您应该避免使用Promise constructor antipattern,否则看起来很好。
  • @Bergi 但问题在于,每次调用和使用该方法时,都会创建一个 new 集合。这不会使用与此方法的另一个执行相同的内存。该集合为每个索引创建一个内存二叉树。另外,您如何建议在这里避免使用反模式?通常有很多IndexLoaders需要解决。

标签: javascript typescript ecmascript-6 es6-promise


【解决方案1】:

结果包含在一个承诺中,如果我理解你的话。因此,您应该简单地返回包含打开连接的对象,然后将其包装在已解决的承诺 (then) 中,并且您应该能够在 then 中执行操作。

这是我拼凑的粗略 javascript 示例。

var p1 = new Promise((res, rej) => { 
   res( something_to_get_my_connection(input) ); //resolve the promise with the connection
}).then( (con) => {
   //Use connection. 
});

如果你的意思是你想要它在 promise 结构之外,我在过去看到过:

let myEstablishedConnection = null;
var p2 = new Promise((res, rej) => { 
   res( something_to_get_my_connection(input) ); //resolve the promise with the connection
}).then( (con) => {
   //Use connection. 
   myEstablishedConnection = con;
   continueProgram(); //This can be several things but I'm assuming the remaidner of the implementation is here. 
});

并且没有通常不赞成的外部范围变量:

var p3 = new Promise((res, rej) => { 
   res( something_to_get_my_connection(input) ); //resolve the promise with the connection
}).then( (con) => {
   continueProgram(con); //This can be several things but I'm assuming the remainder of the implementation is started here. 
});

要等待所有的承诺,你可以使用类似的东西:

Promise.all([p1,p2, p3]).then( () => { proceed(); } ); 

(这些例子是我的头脑,如果有错字或不一致,我很抱歉。promise.all 的用法显然是人为的。)

【讨论】:

  • 使用外部作用域myEstablishedConnection 变量是一种可怕的反模式。不要这样做。
  • 也许当谈到理论上我同意,但我已经看到它曾经在一些 NodeJs 包中取得了巨大的成功和干净的实现。立即想到的是 TestCafe。
  • 我没有说它不能正常工作,我只是说这是一个可怕的模式和there are much better solutions
  • 我明白,但我的意思是,当仔细包装并经过深思熟虑使用时,它并不像在更宏大的背景下讨论时那样可怕。
猜你喜欢
  • 2020-11-03
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 2016-10-04
  • 1970-01-01
相关资源
最近更新 更多