2016-11-16 5 views
0

私はangular2サービスを持っていると私はそれが次の操作を行いたい:このAngle2サービスをやや同期させるにはどうすればよいですか?

  1. のFTPリモートサーバ
  2. にファイルを探す「結果」JSONオブジェクトを構築し、に戻り、それ
  3. からいくつかの行を読みます呼び出し元のコンポーネント

実際に私はステップ1/2の作業をしていますが、もちろんそのすべてが非同期です。だから何が起こっていることは、私はthis.ftpは私のサービスのインスタンスであるサービスには、このコールをやっている私のコンポーネントである:

this.servers = this.ftp.lookForServers(); 

さて、これは正しく、次のようになり、私のFTPサービスのlookForServersメソッドを呼び出します。

lookForServers(){ 
    var servers = []; 
    var whereAreWe = 0; 
    var possibles = ["/path/to/servers/"]; 
    for(var i=0;i<possibles.length;i++){ 
     whereAreWe = i; 
     this.c.list(possibles[i],false,(err,list)=>{ 
     for(var p=0;p<list.length;p++){ 
      console.log(list[p]); 
      var server_version = this.grabLog(possibles[whereAreWe]+list[p].name); 
      servers.push({ 
      name: list[p].name, 
      path: possibles[whereAreWe]+list[p].name, 
      version: server_version 
      }); 
     } 
     }); 
    } 
    return servers; 
    } 

- FTPクライアント、もちろん非同期であるので、この方法は、ほとんどすぐに戻ります - - コールバックが実行し続けながらthis.grabLog(possibles[whereAreWe]+list[p].name);関数呼び出しがthis.cにさらに通話を発信して終わります。これらのコールバックはファイルをダウンロードし、別のコールバック関数がこのファイルを処理します。これは、1行ずつ、非同期的に保存したいさまざまな詳細を選択します。このチェーンの終わりまでに

- 私は最終的にすべての私の詳細情報を持っている:

lineReader.on('close',() => { function - but of course my `this.ftp.lookForServers();` function call has long gone....and the component is none the wiser. 

それでは、どのように私は、この作品は非同期に起こる、と今でも一度コンポーネント私の結果のJSONオブジェクトに戻って通過させることができます仕事は完了しましたか?これはおそらく、サービスコールをコンポーネントコールバックにするにはどうすればいいのでしょうか?

答えて

2

同期して実行する必要はありません。あなたは、lookForServers(およびそれが使っている他の関数は)観測を使うようにし、このような結果に加入する必要があります。ここでは

this.ftp.lookForServers().subscribe((data) => { this.servers = data }); 

は、実装は以下のとおりです。SERVER_VERSION除く

const Client = require('ftp'); 
const fs = require('fs'); 
const readline = require('readline'); 

import { NextObserver } from 'rxjs/Observer'; 
import { Observable } from 'rxjs/Rx'; 

interface server { 
    name: string; 
    path: string; 
    version: string; 
    java_version: string; 
} 

export class FTPClient { 
    username: string; 
    password: string; 
    host: string; 
    port: number; 
    c: any; 

    constructor() { 
    } 

    init(username, password, host, port) { 
     console.log("initiating FTP connection to:" + host + "on port:" + port); 

     this.username = username; 
     this.password = password; 
     this.host = host; 
     this.port = port; 
     this.c = new Client(); 

     console.log("Client created"); 
    } 

    connect() { 
     console.log("About to start connection"); 

     this.c.on('ready',() => { 
      this.c.list((err: any, list: any) => { 
       if (err) throw err; 

       console.dir(list); 
       this.c.end(); 
      }); 
     }); 

     // connect to localhost:21 as anonymous 
     var connectProps = { 
      host : this.host, 
      port : this.port, 
      user : this.username, 
      password : this.password 
     }; 

     console.log("Connecting now..."); 
     this.c.connect(connectProps); 
    } 

    public lookForServers(name: string): Observable<any[]> { 
     return Observable.create((observer: NextObserver <any[]>) => { 
      let servers = []; 
      let whereAreWe = 0; 
      let possibles = [ "/path/to/servers/" ]; 

      for (var i = 0; i < possibles.length; i++) { 
       whereAreWe = i; 

       this.c.list(possibles[ i ], false, (err: any, list: any) => { 
        for (var p = 0; p < list.length; p++) { 
         this.grabMessagesLog(possibles[ whereAreWe ] + list[ p ].name) 
         .subscribe((data: any) => { 
           let server_version = data; 

           servers.push({ 
            name : list[ p ].name, 
            path : possibles[ whereAreWe ] + list[ p ].name, 
            version : server_version 
           }); 

           observer.next(servers); 
           observer.complete(); 
          } 
         ); 
        } 
       }); 
      } 
     }); 
    } 

    grabMessagesLog(path): Observable<any> { 
     return Observable.create((observer: NextObserver <any>) => { 
      let result = ''; 
      let unix = Math.round(+new Date()/1000); 
      this.c.binary(function(err) { 
       console.log(err); 
      }); 

      this.c.get(path + "/logs/messages.log", (err, stream) => { 
       if (err) throw err; 

       stream.once('close',() => { 
        this.c.end(); 
        this.getServerMetadataFromMessagesLog(unix + "_messages.log") 
        .subscribe((data) => { 
         stream.pipe(fs.createWriteStream(unix + "_messages.log")); 

         observer.next(data); 
         observer.complete(); 
        }); 
       }); 
      }); 
     }); 
    } 

    getServerMetadataFromMessagesLog(path): Observable<any> { 
     return Observable.create((observer: NextObserver <any>) => { 
      let lineReader = readline.createInterface({ 
       input : fs.createReadStream(path) 
      }); 

      let server_version = ""; 
      let java_version = ""; 
      let line_no = 0; 

      lineReader.on('line', function(line) { 
       line_no++; 
       console.log("line number is:" + line_no); 

       if (line.includes("STUFF") && line.includes("FLAG2") && line_no == 2) { 
        var first = line.split("FLAG2")[ 1 ]; 
        var last = first.split(" (")[ 0 ]; 
        var version = "FLAG2" + last; 
        this.server_version = version; 
        console.log("version is:" + version); 
       } 

       if (line.includes("java.version =")) { 
        var javav = line.split("java.version =")[ 1 ]; 
        this.java_version = javav; 
        lineReader.close(); 
       } 

       console.log('Line from file:', line); 
      }); 

      lineReader.on('close',() => { 
       var res = { 
        version : server_version, 
        java_version : java_version 
       }; 

       alert("RES IS:" + JSON.stringify(res)); 

       observer.next(res); 
       observer.complete(); 
      }); 
     }); 
    } 
} 
+0

だから、他のコールバックから返ったものを購読するときはいつでも、購読されたコールバックに引き戻されますか? – RenegadeAndy

+0

はい。 Observable を返すため、サブスクリプション(データ)は 'any'です。 –

+0

ObservableとNextObserverはどこからインポートしますか? – RenegadeAndy

1

角度

function recursiveWait(server_version){ 

    if(server_version != null){ 
     return; 
    } 

    $timeout(function(){recursiveWait()}, 500); 
} 

$timeout機能を再帰機能を使用して試してみて、それをここに配置します。それは!= nullをかどう

 console.log(list[p]); 
     var server_version = this.grabLog(possibles[whereAreWe]+list[p].name); 
     recursiveWait(server_version); 
     servers.push({ 
     name: list[p].name, 

これはVARを聞いてきます、それが呼び出されます、それは同じだ場合500msの関数に戻ります。そうでなければ、関数を返して終了し、コードを続行します。

+0

は*必ず*としてnullになりますこのコードの残りの部分がasync ...を実行するので、this.grabLog関数はほぼ即座に戻ります。したがって、コールバックのそれぞれにコンテキストがあり、それを待つ変数の種類をチェックしたいと仮定します。 ?また、私は関数のタイムアウト呼び出しは "recursiveWait - recursiveF"でなくてはならないと思いますか? – RenegadeAndy

+0

server_versionは、しばらくの間、!= nullになります。再帰関数は、その変更を待つことになります。非同期関数は、jsで**タイムアウト**を行い、nullリターンを強制します。しかし、コードは動作し続け、終了したら値を返します。 – driconmax

+0

これは500ms後の試行であり、すべてのタイミングに基づいています。これはプロセッサとネットワークの速度に基づいて非常にうまく機能しない可能性があります。私はこのタイムアウトを増やすことができますが、解決策としてやや不安定なように思えますか?代替アプローチはありますか? – RenegadeAndy

関連する問題