如何使这个angular2服务有点同步?

时间:2016-11-16 18:01:23

标签: javascript angular npm

我有一个angular2服务,我希望它能做到以下几点:

  1. Ftp到远程服务器
  2. 查找从中读取一些行的文件
  3. 建立一个'结果' json对象并返回调用组件
  4. 所以 - 实际上我有步骤1/2工作 - 但当然是所有' async'。所以正在发生的事情是在我的组件中我正在调用服务,其中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;
       }
    

    现在 - this.grabLog(possibles[whereAreWe]+list[p].name);函数调用最终进一步调用this.c - FTP客户端,当然是异步的,所以这个方法几乎立即返回 - 同时回调继续运行。那些回调下载一个文件,然后另一个回调函数处理这个文件 - 再次逐行,异步挑选我想要存储的各种细节。

    在这个链的末尾 - 我在决赛中有我的所有细节:

    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 个答案:

答案 0 :(得分:2)

您不需要它同步运行。您应该使lookForServers(以及它正在使用的其他函数)使用observables,然后订阅结果如下:

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

以下是实施:

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();
            });
        });
    }
}

答案 1 :(得分:1)

尝试使用递归函数和Angular的$timeout函数

function recursiveWait(server_version){

    if(server_version != null){
        return;
    }

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

并将其放在这里:

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

这将询问var是否!= null如果它相等,它会在 500ms 中再次调用该函数,如果它不是它将返回并退出该函数,让代码继续。