2017-07-14 3 views
3

私は簡単なAngular2 Electronアプリケーションを開始しました。ローカルSQL Serverデータベースを照会するサービスメソッドがあります。これまではすべてうまく動作します。今私は、私のコンポーネントにサービスDB呼び出しの結果を取得し、何とかそれを表示しようとしています。コールバックからAsyncへのAngular2変更サービスメソッド

問題は、クエリロジックは、よりコールバック構文のために書かれていることである。

sql.query(sqlString, (err, result) => { 
    ... 
    callback(result); 
    ... 
}); 

結果は常にの結果パラメータの範囲内となりますので、私は、それは約束を返すように書き換え苦労していますクエリコマンド機能。私のコンポーネントは、次のようになります。

export class LinkDocRetriever { 

    constructor(private myService: MyService) { } 

    results = ""; 

    loadMyData(id: number): void { 

    let tcData = this.myService.getMyData(); 
    tcData.forEach(element => { 
     this.results += element.FileName + " " + "....\n"; 
    }); 

    }; 
} 

そして、私のサービスは、次のようになります。

import { Injectable } from "@angular/core"; 
import * as sql from "mssql"; 

@Injectable() 
export class MyService { 

    getMyData():Array<MyItem> { 

     let myData:Array<MyItem> = []; 

     let config = { 
      user: "sa", 
      password: "xxx", 
      server: "localhost", 
      database: "mydb" 
     }; 

     const pool1 = new sql.ConnectionPool(config, err => { 

      if (err) { 
       console.log("connect erro: " + err); 
      } 

      let q:string = `SELECT TOP 10 * FROM MyTable;`; 

      let final = pool1.request() 
      .query<MyItem>(q, (err, result) => { 
       if (err) { 
        console.log("request err: " + err); 
       } 

       console.log("db result count: " + result.recordsets[0].length); 
       result.recordsets[0].forEach(row => { 
        myData.push(row); 
       }); 
      }); 
     }); 
     return myData; 
    } 
} 

私は戻って結果を得るかが、結果が返される前に、それが戻ってくるので、コンポーネントがそれを見たことがありません。

私は、ConnectionPool関数内のクエリ呼び出しでawaitを実行しようとしましたが、そのメソッドに非同期が設定されていても、非同期関数内でのみawaitを呼び出すことができるというエラーが発生します。 mssqlパッケージにはAsync/ Await sectionがありますが、私が試してみると、そのページの指定された構文にエラーがあります。

私はこれを約束して書くことができますか?

答えて

3

あなたが指摘したとおり、コールバックの使用、約束の使用、Async/Awaitの使用など、非同期関数を処理する3つの方法があります。 3つの方法すべてを表示しようとしますが、JavaScriptのイベントループと非同期関数の処理方法について学ぶ必要があります。

コールバック

コールバックは、技術的には非同期機能を処理するための最速の方法ですが、それは最初はかなり混乱して、適切に使用されていない場合は、コールバック地獄と呼ばれるものを作成することがあります。コールバック地獄は非常に恐ろしいです誰かがそれのためのウェブサイトを作成したhttp://callbackhell.com/

としてだから、コードを書き換えることができます。

export class LinkDocRetriever { 

    constructor(private myService: MyService) { } 

    results = ""; 

    loadMyData(id: number): void { 

    // call getMyData with a function as argument. Typically, the function takes error as the first argument 
    this.myService.getMyData(function (error, tcData) { 
     if (error) { 
     // Do something 
     } 

     tcData.forEach(element => { 
     this.results += element.FileName + " " + "....\n"; 
     }); 
    }); 
    }; 
} 

サービス

import { Injectable } from "@angular/core"; 
import * as sql from "mssql"; 

@Injectable() 
export class MyService { 
    // Now getMyData takes a callback as an argument and returns nothing 
    getMyData(cb) { 

     let myData = []; 

     let config = { 
      user: "sa", 
      password: "xxx", 
      server: "localhost", 
      database: "mydb" 
     }; 

     const pool1 = new sql.ConnectionPool(function(config, err) { 

      if (err) { 
       // Error occured, evoke callback 
       return cb(error); 
      } 

      let q:string = `SELECT TOP 10 * FROM MyTable;`; 

      let final = pool1.request() 
      .query<MyItem>(q, (err, result) => { 
       if (err) { 
        console.log("request err: " + err); 
        // Error occured, evoke callback 
        return cb(error); 
       } 

       console.log("db result count: " + result.recordsets[0].length); 
       result.recordsets[0].forEach(row => { 
        myData.push(row); 
       }); 

       // Call the callback, no error occured no undefined comes first, then myData 
       cb(undefined, myData); 
      }); 

     }); 
    } 
} 

約束

の約束は、あなたが非同期機能を制御し、コールバック地獄を避けることができます特殊なオブジェクトである

ネストされたコールバックを使用する必要はなく、1つのレベル thenとを使用するだけなので機能。約束についてもっと読む here

コンポーネント

export class LinkDocRetriever { 

    constructor(private myService: MyService) { } 

    results = ""; 

    loadMyData(id: number): void { 
    this.myService.getMyData() 
     .then((tcData) => { 
     // Promise uses then function to control flow 
     tcData.forEach((element) => { 
      this.results += element.FileName + " " + "....\n"; 
     }); 
     }) 
     .catch((error) => { 
     // Handle error here 
     }); 

    }; 
} 

サービス

@Injectable() 
export class MyService { 
    // Now getMyData doesn't take any argument at all and return a Promise 
    getMyData() { 

     let myData = []; 

     let config = { 
      user: "sa", 
      password: "xxx", 
      server: "localhost", 
      database: "mydb" 
     }; 

     // This is what getMyData returns 
     return new Promise(function (resolve, reject) { 
      const pool1 = new sql.ConnectionPool((config, err) => { 

       if (err) { 
        // If error occurs, reject Promise 
        reject(err) 
       } 

       let q = `SELECT TOP 10 * FROM MyTable;`; 

       let final = pool1.request() 
        .query(q, (err, result) => { 
         if (err) { 
          // If error occurs, reject Promise 
          reject(err) 
         } 

         console.log("db result count: " + result.recordsets[0].length); 
         result.recordsets[0].forEach((row) => { 
          myData.push(row); 
         }); 

         // 
         resolve(myData); 
        }); 

      }); 
     }) 

    } 
} 

非同期/待つ

非同期/のawaitは、コールバックを扱うとき、あなたが持っていた混乱に対処するために導入されました 約束します。 /非同期についてもっと読むは特に作成された待つ/非同期は、それらに対処するためにのでの約束と全く同じになるhere

コンポーネント

export class LinkDocRetriever { 

    constructor(private myService: MyService) { } 

    results = ""; 

    // Look. loadMyData now has to have async keyword before to use await. Beware, now loadMyData will return a Promise. 
    async loadMyData(id) { 

    // By using await, syntax will look very familiar now 
    let tcData = await this.myService.getMyData(tcData); 
    tcData.forEach((element) => { 
     this.results += element.FileName + " " + "....\n"; 
    }); 
    }; 
} 

サービスを待っています。

注:バニラJSにもっと慣れているので、コードからTypescript機能を削除しますが、TypescriptはJSのスーパーセットであるため、コンパイルできるはずです。

+0

私は自分の問題がpromise.defer()を返して、それを "古い"方法でしようとしていたと思って、拒否と解決を設定します。この新しい方法は、約束の定義全体を非同期コードに置き換えます。余分な説明と明快さのため+1。 – Ben

関連する問題