从对话框中选择目录后,在Angular2 + Electron应用程序中加载异步图像

时间:2016-09-25 10:26:28

标签: image angular electron observable

所以我在Electron + Angular2应用程序中有以下内容:

import {Component} from '@angular/core';
import * as fs from "fs";
import {ImageFile, KeepAction, RetouchAction, PrivateAction, DeleteAction} from "./components/imageFile";
import {remote} from 'electron';
import {
    DomSanitizationService,
        SafeUrl
} from '@angular/platform-browser';
import {Observable} from "rxjs";


let dialog = remote.dialog;

@Component({
    selector: 'app',
    template: `
        <button id="openDir" (click)="openDir()">Open</button>
        <br />
        <img id="processingImage" [src]="currentImg | async"/>
        <br />
        <button id="nextImage" (click)="nextImage()">Next Image</button>
  `
})

export class AppComponent {

    dirPath: string;
    currentImg: Observable<SafeUrl>;
    fileSet: string[] = [];
    currentFile: number = 0;

    constructor(private sanitization: DomSanitizationService) {
        this.dirPath = "";
        this.currentImg = Observable.of<SafeUrl>(null);
    }

    /**
     * <p>Shows a dialog for opening the directory to be processed.</p>
     * <p>After a directory is selected, it will be analyzed and all images will be loaded to be organized.</p>
     */
    openDir() {
        dialog.showOpenDialog({defaultPath: 'C:\\', properties: ['openDirectory']}, (fileNames) => {
            //TODO assert only one file name is present
            this.dirPath = fileNames[0];
            fs.readdir(this.dirPath, (e, f) => this.loadFiles(e, f));
        });
    }

    nextImage() {
        if (this.currentFile < this.fileSet.length - 1) {
            this.currentFile++;
            this.setSanitizedCurrentImage();
        }
    }

    setSanitizedCurrentImage(){
        let currentPath = this.fileSet[this.currentFile];
        this.currentImg = Observable.of(this.sanitization.bypassSecurityTrustUrl(currentPath));
    }

    loadFiles(err: NodeJS.ErrnoException, files: string[]): void {
        this.fileSet = [];
        this.currentFile = 0;

        files.forEach((it) => {
            var filePath = this.dirPath + '/' + it;

            if (fs.statSync(filePath).isFile()) {
                this.fileSet.push(filePath);
            }
        });
        this.setSanitizedCurrentImage();
    }

}

当点击“打开”按钮时,会出现一个对话框,我选择一个目录并尝试加载setSanitizedCurrentImage()的第一张图片,该图片适用于nextImage但不能打开图片。

我想这是由于异步方法showOpenDialog()showOpenDialog(),但我无法刷新当前图像值。

1 个答案:

答案 0 :(得分:0)

我能够使用Promise解决此问题并在执行showOpenDialogreaddir回调后解析它。

TLDR

 openDir() {
        new Promise((resolve, reject) => {
            dialog.showOpenDialog({defaultPath: 'C:\\', properties: ['openDirectory']}, (fileNames) => {
                //TODO assert only one file name is present
                this.dirPath = fileNames[0];
                fs.readdir(this.dirPath, (e, f) => {
                    this.loadFiles(e, f);
                    resolve();
                });
            })
        }).then(() => this.setSanitizedCurrentImage());
    }

完整代码:

import {Component} from '@angular/core';
import * as fs from "fs";
import {ImageFile, KeepAction, RetouchAction, PrivateAction, DeleteAction} from "./components/imageFile";
import {remote} from 'electron';
import {
    DomSanitizationService,
        SafeUrl
} from '@angular/platform-browser';
import {Observable} from "rxjs";


let dialog = remote.dialog;

@Component({
    selector: 'app',
    template: `
        <button id="openDir" (click)="openDir()">Open</button>
        <br />
        <img id="processingImage" [src]="currentImg | async"/>
        <br />
        <button id="nextImage" (click)="nextImage()">Next Image</button>
  `
})

export class AppComponent {

    dirPath: string;
    currentImg: Observable<SafeUrl>;
    fileSet: string[] = [];
    currentFile: number = 0;

    constructor(private sanitization: DomSanitizationService) {
        this.dirPath = "";
        this.currentImg = Observable.of<SafeUrl>(null);
    }

    /**
     * <p>Shows a dialog for opening the directory to be processed.</p>
     * <p>After a directory is selected, it will be analyzed and all images will be loaded to be organized.</p>
     */
    openDir() {
        new Promise((resolve, reject) => {
            dialog.showOpenDialog({defaultPath: 'C:\\', properties: ['openDirectory']}, (fileNames) => {
                //TODO assert only one file name is present
                this.dirPath = fileNames[0];
                fs.readdir(this.dirPath, (e, f) => {
                    this.loadFiles(e, f);
                    resolve();
                });
            })
        }).then(() => this.setSanitizedCurrentImage());
    }

    nextImage() {
        if (this.currentFile < this.fileSet.length - 1) {
            this.currentFile++;
            this.setSanitizedCurrentImage();
        }
    }

    setSanitizedCurrentImage(){
        let currentPath = this.fileSet[this.currentFile];
        this.currentImg = Observable.of(this.sanitization.bypassSecurityTrustUrl(currentPath));
    }

    loadFiles(err: NodeJS.ErrnoException, files: string[]): void {
        this.fileSet = [];
        this.currentFile = 0;

        files.forEach((it) => {
            var filePath = this.dirPath + '/' + it;

            if (fs.statSync(filePath).isFile()) {
                this.fileSet.push(filePath);
            }
        });
    }

}