2017-01-31 37 views
0

我不知道如何遍歷數組併發送每個項目鏈接的承諾。我試圖在下面定義DBSchema.executeMigrations(詳情請參閱評論)。如何鏈接承諾從靜態數組參數在打字稿

假設migrations會隨着時間而增長。所以,現在只有3個參數,但明年可能會達到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

讓承諾按順序運行和解決的一個簡單方法是用Array.prototype.reduce()來迭代它們。這樣,您可以立即解析承諾開始迭代,並將承諾的執行順序與來自數組的下一個值鏈接起來。

您的exec()函數是用所謂的deferred anti-pattern/explicit promise construction pattern實現的,這被認爲是不好的做法,應該避免。沒有必要創建一個新的承諾,而你應該返回_this.get()

重構你的函數返回現有的承諾,而不是將使它看起來像這樣

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(...)

+0

乾杯,夥計,感謝您的快速和真棒迴應...... exec()中'then'行的什麼部分是不必要的? – jsharpe

+0

不客氣!如果你仔細想一下,'res'的值是從'db.executeSql()'返回/解析的,所以不需要添加額外的'.then()'來重新返回結果。我將它包含在代碼中僅僅是爲了說明實際返回的結果。看看[這個jsfiddle](https://jsfiddle.net/0sL1ffa4/)來演示它! –