电子打开对话框窗口遇到了非常奇怪的错误。每当我打开它时,它就会挂起并且应用程序冻结。

逻辑很简单,我有一个使用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)会导致与第一个相同的问题。

08-07 09:23