Angular CLI 與 Electron通信

Angular 4 CLI與Electron之間

Angular 4 CLI與Electron之間的通信,一開始做就心里沒底,Electron與渲染頁之間的通信看起來是簡單的,大概是如下這樣,示例代碼出自W3Cschool。具體API在這里先不談冠场,后面打算總結(jié)一下W3Cschool的這個教程点额。

在主進(jìn)程里:

// In main process.
const ipcMain = require('electron').ipcMain;
ipcMain.on('asynchronous-message', function(event, arg) {
    console.log(arg);  // prints "ping"
    event.sender.send('asynchronous-reply', 'pong');
});

ipcMain.on('synchronous-message', function(event, arg) {
    console.log(arg);  // prints "ping"
    event.returnValue = 'pong';
});

在渲染進(jìn)程里:

// In renderer process (web page).
const ipcRenderer = require('electron').ipcRenderer;
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"

ipcRenderer.on('asynchronous-reply', function(event, arg) {
    console.log(arg); // prints "pong"
});
ipcRenderer.send('asynchronous-message', 'ping');

但是怎樣在Angular4 CLI 中使用呢琳要?肯定不能完全依照上面的代碼课幕,一番查找污桦,在Github這里找到一個demo亭姥,工程中的electron.service.ts文件是Electron內(nèi)外通信的關(guān)鍵代碼粮揉。

from src/app/providers/electron.service.ts

import { Injectable } from '@angular/core';

// If you import a module but never use any of the imported values other than as TypeScript types,
// the resulting javascript file will look as if you never imported the module at all.
import { ipcRenderer } from 'electron';
import * as childProcess from 'child_process';

@Injectable()
export class ElectronService {

    ipcRenderer: typeof ipcRenderer;
    childProcess: typeof childProcess;
    constructor() {
        // Conditional imports
        if (this.isElectron()) {
            this.ipcRenderer = window.require('electron').ipcRenderer;
            this.childProcess = window.require('child_process');
            console.log('Electron available!')
        } else {
            console.log('Electron not available!')
        }
    }
    isElectron = () => {
        return window && window.process && window.process.type;
    }
}

然而我在我的工程中是獲得不到window對象的侨拦,后來發(fā)現(xiàn)在typings.d.ts文件中缺少對window的定義,于是加入對window的定義:

from src/typings.d.ts

/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
    id: string;
}

declare var window: Window;
interface Window {
    process: any;
    require: any;
}

因為我的工程很多地方都可能用的渲染進(jìn)程與主進(jìn)程之間的交互狱从,所以將這部分代碼做成一個服務(wù),然后在app.module.ts中引用,最終代碼如下:

from src/app/services/electron.service.ts

import { Injectable } from '@angular/core';

// If you import a module but never use any of the imported values other than as TypeScript types,
// the resulting javascript file will look as if you never imported the module at all.
import { ipcRenderer } from 'electron';
import * as childProcess from 'child_process';

@Injectable()
export class ElectronService {

    ipcRenderer: typeof ipcRenderer;
    childProcess: typeof childProcess;

    constructor() {
        // Conditional imports
        if (this.isElectron()) {
            this.ipcRenderer = window.require('electron').ipcRenderer; console.log(this.ipcRenderer);
            this.childProcess = window.require('child_process');
            console.log('In Electron App!')
        } else {
            console.log('Not in Electron App!')
        }
    }

    private isElectron = () => {
        return window && window.process && window.process.type;
    };

    syncSend(key, value) {
        this.ipcRenderer.sendSync(key, value);
    }
}

這不是最終最終的代碼,但已足以說明問題埠戳。isElectron函數(shù)作用是檢查當(dāng)前運行環(huán)境整胃,比如現(xiàn)在在Electron Shell中打印In Electron App!,否則打印Not in Electron App!蛮寂。

from src/app/app.module.ts

...
import { SubmitService } from './services/submit.service';
...
@NgModule({
    imports: [
        ...
    ],
    declarations: [
       ...
    ],
    providers: [{
        provide: LocationStrategy,
        useClass: HashLocationStrategy
    }, SubmitService, ElectronService ],
    bootstrap: [ AppComponent ]
})
export class AppModule { }

以上其實還好范抓,因為之前沒用過蜕该,所以寫出也是時間問題。其實困擾著我大概一天的問題是這個蹋盆,先上代碼:

from src/app/services/submit.service.ts

/**
* Created by randy on 2017/7/4.
*/
import {Injectable} from '@angular/core';
import {Http, Response} from '@angular/http';
import {Headers, RequestOptions} from '@angular/http';
import {ElectronService} from '../services/electron.service'
import 'rxjs/add/operator/toPromise';

@Injectable()
export class SubmitService {
    constructor(private http: Http, public electronService: ElectronService) {
    }

    getSubmit(submitUrl: string): Promise<string> {
        return this.http.get(submitUrl, {withCredentials: true})
        .toPromise()
        .then((res: Response) => {
            const body = JSON.stringify(res.json());
            if (res.json().msg === '404') {
                this.electronService.syncSend('key', 'Need to update!');
            }
            return body || '';
        })
        .catch(this.handleError);
    }

    postSubmit(submitUrl: string, params: string): Promise<string> {
        const options = new RequestOptions({withCredentials: true});
        return this.http.post(submitUrl, params, options)
        .toPromise()
        .then((res: Response) => {
            const body = JSON.stringify(res.json());
            if (res.json().msg === '404') {
                this.electronService.syncSend('key', 'Need to update!');
            }
            return body || '';
        })
        .catch(this.handleError);
    }

    private handleError(error: Response | any) {
        // In a real world app, we might use a remote logging infrastructure
        let errMsg: string;
        if (error instanceof Response) {
            const body = error.json() || '';
            const err = body.error || JSON.stringify(body);
            errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
        } else {
            errMsg = error.message ? error.message : error.toString();
        }
        console.error(errMsg);
        return Promise.reject(errMsg);
    }
}

這個也是一個服務(wù)费薄,是做HTTP GETPOST提交的服務(wù),我的邏輯是根據(jù)請求的返回數(shù)據(jù)栖雾,跟Electron通信楞抡,起初我的http.request函數(shù)后的then里是封裝的一個函數(shù),跟catch一樣析藕,那么問題來了召廷,我做的一直死活獲取不到this,獲取不到this自然也沒辦法獲得從類構(gòu)造函數(shù)傳入的electron對象账胧,最后從這里找到答案竞慢,Promise會引起上下文丟失,使用箭頭函數(shù)可以解決找爱,前幾天以為學(xué)到Lambda表達(dá)式的我又學(xué)到了梗顺。

PS: May be this page helps later.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市车摄,隨后出現(xiàn)的幾起案子寺谤,更是在濱河造成了極大的恐慌,老刑警劉巖吮播,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件变屁,死亡現(xiàn)場離奇詭異,居然都是意外死亡意狠,警方通過查閱死者的電腦和手機(jī)粟关,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來环戈,“玉大人闷板,你說我怎么就攤上這事澎灸。” “怎么了遮晚?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵性昭,是天一觀的道長。 經(jīng)常有香客問我县遣,道長糜颠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任萧求,我火速辦了婚禮其兴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘夸政。我一直安慰自己元旬,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布守问。 她就那樣靜靜地躺著法绵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酪碘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天盐茎,我揣著相機(jī)與錄音,去河邊找鬼。 笑死枢里,一個胖子當(dāng)著我的面吹牛邢滑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窑业,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钦幔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了常柄?” 一聲冷哼從身側(cè)響起鲤氢,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎西潘,沒想到半個月后卷玉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡喷市,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年相种,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片品姓。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡寝并,死狀恐怖箫措,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衬潦,我是刑警寧澤斤蔓,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站别渔,受9級特大地震影響附迷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哎媚,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一喇伯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拨与,春花似錦稻据、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淤毛,卻和暖如春今缚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背低淡。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工姓言, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔗蹋。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓何荚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親猪杭。 傳聞我的和親對象是個殘疾皇子餐塘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容