如何从typescript中的静态参数数组中链接promises

时间:2017-01-31 21:24:40

标签: typescript promise

我不确定如何迭代数组并向每个项目发送链接的承诺。我正在尝试在下面定义DBSchema.executeMigrations(详见评论)。

假设migrations会随着时间的推移而增长。所以,它现在只有3个args,但明年可能是100个。我需要这个迭代。

export class DBConnection {
  exec(query): Promise<any> {
    let _this = this;
    return new Promise((resolve) => {
      _this.get().then((db) => {
        db.executeSql(query, {}).then(
          (result) => {
            resolve(result);
          },
          (err) => {
            console.log('Unable to execute query: ' + err.message);
          }
        );
      });
    });
  }
}


export class DBSchema {

  constructor(public db_connection: DBConnection){};

  static migrations = [
    "CREATE TABLE IF NOT EXISTS events(id INTEGER PRIMARY KEY NOT NULL, title STRING)",
    "CREATE TABLE IF NOT EXISTS news(id INTEGER PRIMARY KEY NOT NULL, title STRING)",
    "CREATE TABLE IF NOT EXISTS whatever(id INTEGER PRIMARY KEY NOT NULL, title STRING)"
  ];

  executeMigrations(): any {
    // send each migration to db_connection.exec
    // do it in order
    // return a promise that resolves when all of them are done
  }
}

1 个答案:

答案 0 :(得分:1)

让promises按顺序运行和解析的一种简单方法是使用Array.prototype.reduce()迭代它们。这样,您可以使用立即解析的promise启动迭代,并使用将来自数组的下一个值链接promises的执行顺序。

您的exec()函数是使用所谓的deferred anti-pattern/explicit promise construction pattern实现的,这被认为是不好的做法,应该避免。您不需要创建新的承诺,而应该从_this.get()返回一个承诺。

重构你的函数以返回现有的promise会改为使它看起来像这样

 exec(query): Promise<any> {
    let _this = this;
    return _this.get().then((db) => {
        return db.executeSql(query, {})
            .then((res) => { return res }) //not really necessary but to make it more clear
            .catch((err) => {
               console.log('Unable to execute query: ' + err.message);
          }
        );
      });
  }

并使用Array.prototype.reduce(),您可以让所有查询按顺序运行,并使用这样的函数等待彼此

  executeMigrations(): Promise<any> {
      return DBSchema.migrations.reduce((previousValue: Promise<string>, currentValue: string): Promise<any> => {
          return previousValue.then(() => {
              return this.db_connection.exec(currentValue);
          });
      }, Promise.resolve());
  }

executeMigrations()返回的承诺在所有“内部”承诺得到解决后得到解决,让您可以轻松地继续使用常规.then()的其他内容,就像executeMigrations().then(...)一样