电子打开对话框窗口遇到了非常奇怪的错误。每当我打开它时,它就会挂起并且应用程序冻结。
逻辑很简单,我有一个使用typescript-fsa
库创建异步操作的助手。它的目的是调用一个promise,并在完成时调用已完成/失败的操作。这个帮助程序不是问题,因为它适用于应用程序中的其他100个史诗,但是它可能会与电子对话发生冲突。
export function makeAsyncEpic<T, P, S>(
actionCreator: AsyncActionCreators<T, P, S>,
asyncMethod: (params: T, state: ApplicationState, action$) => Promise<P>,
filter?: (action$: Observable<Action>, state: ApplicationState) => boolean,
) {
return makeObservableEpic(actionCreator, (p, s, a) => Observable.fromPromise(asyncMethod(p, s, a)), filter);
}
export function makeObservableEpic<T, P, S>(
{ started, done, failed }: AsyncActionCreators<T, P, S>,
observable: (params: T, state: ApplicationState, action$) => Observable<P>,
filter?: (action$: Observable<Action>, state: ApplicationState) => boolean,
) {
return (action$: Observable<Action>, store: { getState: () => ApplicationState }) =>
action$
.filter(started.match)
.filter(() => (filter === undefined ? true : filter(action$, store.getState())))
.switchMap(action =>
observable(action.payload, store.getState(), action$)
.map(result => {
return done({
params: action.payload,
result,
});
})
.catch(error => {
return Observable.of(
failed({
params: action.payload,
error,
}),
);
}),
);
}
当我调用action.openRepository.started时,以下史诗冻结了该应用程序:
const remote = electron.remote;
const mainProcess = remote.require("./dialog");
export const openDirectoryEpic = makeAsyncEpic(actions.openRepository, mainProcess.openDirectory);
令人惊讶的是,如果我将其更改为
export const openDirectoryEpic = makeAsyncEpic(actions.openRepository, async () => {
const directory = await mainProcess.openDirectory();
return directory;
});
它工作正常。它不是等效的吗?可能的原因是什么?
编辑:
我什至可以在这里删除async / await,并像这样放置它并起作用:
export const openDirectoryEpic1 = makeAsyncEpic(actions.openRepository, () => mainProcess.openDirectory());
() => mainProcess.openDirectory()
是否等效于mainProcess.openDirectory
?EDIT2:openDirectory是通过以下方式实现的:
import { dialog, ipcMain } from "electron";
import { mainWindow } from "./main";
export const openDirectory = (): Promise<{ directory: string }> =>
new Promise((resolve, reject) => {
console.log("Opening dialog");
const property: "openDirectory" = "openDirectory";
const options = {
title: "Select Repository",
properties: [property],
};
try {
dialog.showOpenDialog(mainWindow, options, (files: string[]) => {
if (files && files.length === 1) {
resolve({ directory: files[0] });
} else {
reject(`Error when opening directory: ${files}`);
}
});
} catch (err) {
reject(err);
}
});
最佳答案
使用makeAsyncEpic(actions.openRepository, mainProcess.openDirectory);
隐式地将所有参数传递给openDirectory函数,并且electron.remote
需要打包/包装每个参数,然后才能将其发送到主处理器。
在您的情况下,最后一个参数是Observable
类型,Electron可能无法打包。
使用makeAsyncEpic(actions.openRepository, () => mainProcess.openDirectory())
不会将任何参数传递给openDirectory
函数,因此Electron不会有任何问题。
我猜测以下语法(p, s, a) => mainProcess.openDirectory(p, s, a)
会导致与第一个相同的问题。