我在 Electron 打开对话框窗口中遇到非常奇怪的错误。每当我打开它时,它就会挂起并且应用程序被卡住。
逻辑很简单,我有一个使用 typescript-fsa
库创建异步操作的助手。它的目的是调用一个 promise ,并在完成时调用完成/失败的操作。这不是这个助手的问题,因为它适用于应用程序中的其他 100 个史诗,但它可能会做一些与 Electron 对话框冲突的事情。
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,
}),
);
}),
);
}
当我调用 actions.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
需要先打包/package 每个参数,然后才能将其发送到主处理器。
在您的情况下,最后一个参数是 Observable
type 和 Electron 在打包时可能会出现问题。
使用makeAsyncEpic(actions.openRepository, () => mainProcess.openDirectory())
您没有将任何参数传递给 openDirectory
函数所以 Electron 不会有任何问题。
我猜测以下语法 (p, s, a) => mainProcess.openDirectory(p, s, a)
将导致与第一个相同的问题。
关于javascript - 使用没有 async/await 的 Promise 时, Electron 打开对话框会挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49241837/