【问题标题】:Waiting for multiple ipc calls to complete before continuing in electron/redux等待多个 ipc 调用完成,然后继续使用电子/redux
【发布时间】:2016-06-29 09:29:45
【问题描述】:

我正在使用 Electron、React 和 Redux 开发一个应用程序。在程序启动时,我在渲染进程和主进程之间进行了几次异步 ipc 调用,并将结果保存在存储中。

// in the main app component
componentWillMount() {
    const { store } = this.context;
    store.dispatch(fetchOptions());
    store.dispatch(fetchRequirements());
    store.dispatch(fetchStats());
    /* miracle function */
},

// actions.js
export function fetchOptions() {
    return dispatch => {
        dispatch(requestOptions());
        ipcRenderer.on('sendOptions', function(event, arg) {
            dispatch(receiveOptions(arg));
        });
        ipcRenderer.send('requestOptions', '');
    };
}
// others accordingly

receiveOptions(arg)receiveRequirements(arg)receiveStats(arg) 是动作创建者,最后reducer 会将响应保存在商店中。

store.dispatch(fetchStats()) 之后,我想直接调度另一个操作,以根据加载到存储中的值进行一些计算。但是,此操作通常会在来自 ipc 的响应到达之前发送。

我发现this discussion 有类似的问题,但他们使用fetch 而不是ipc 消息进行api 调用,我不知道如何将他们的想法应用于我的问题。

所以这是我的问题:如何让程序在继续之前等待所有渠道的响应?

编辑:当我在 ipc 调用后为调度设置一个长度为 0 的时间时,它至少可以立即响应,但是当响应需要更长的时间时它当然没有帮助。

store.dispatch(fetchOptions());
store.dispatch(fetchRequirements());
store.dispatch(fetchStats());

setTimeout(function() {
    store.dispatch(calculateThis());
    store.dispatch(calculateThat());
}, 0);

【问题讨论】:

  • 获取函数的返回类型是什么?如果它们是承诺,你可以使用Promise.all() 做一些事情——比如派发一个动作——当它们都被解决时。如果他们不返回承诺,也许你可以让他们这样做?
  • 获取函数不返回承诺,我真的不知道如何让它们这样做。

标签: javascript reactjs ipc redux electron


【解决方案1】:

一个使用Promises的例子

假设

我不熟悉您的icpRenderer 的工作方式,或者调度完成时的确切情况。我将假设调用dispatch(receiveOptions(arg))返回后完成调度

    ipcRenderer.on('sendOptions', function(event, arg) {
        dispatch(receiveOptions(arg));
    });

如果 dispatch() 是异步的,这将不起作用(除非你等到 dispatch() 完成后才解决承诺)。

如果我的假设是正确的

你应该能够return像这样收到“承诺”(并解决它)

    // actions.js
    export function fetchOptions(promise) {
        return dispatch => {
            dispatch(requestOptions());
            ipcRenderer.on('sendOptions', function(event, arg) {
                dispatch(receiveOptions(arg));
                if (promise) promise.resolve(); // Resolve the promise
            });
            ipcRenderer.send('requestOptions', '');
        }
    }
    // return Promises others accordingly

(请注意,您可以在不传递“promise”的情况下调用 fetchOptions,因为我们仅在存在 promise 时才调用 promise.resolve()。因此,这不应使您现有的代码复杂化。)

为了等待承诺解决,你可以这样做

    // in the main app component
    componentWillMount() {
        const { store } = this.context;
        const promises = [
            new Promise((resolve, reject) =>
                store.dispatch(fetchOptions({resolve, reject}))),
            new Promise((resolve, reject) =>
                store.dispatch(fetchRequirements({resolve, reject}))),
            new Promise((resolve, reject) =>
                store.dispatch(fetchStats({resolve, reject})))
        ];
        Promise.all(promises).then(() =>
            // Dispatch another action after the first three dispatches are completed.
        );
    },

代码不是很干净,但希望它至少可以工作。

【讨论】:

  • 谢谢。您的假设是正确的:ipcRenderer.send 在通道 requestOptions 上发送消息,而 ipcRenderer.on 在通道 sendOptions 上打开侦听器并将响应 args 发送到调度程序。
  • 好!让我知道这是否能解决您的问题。
  • 很遗憾,您的解决方案不起作用。 Redux 的 dispatch 函数需要一个格式为 {type: receiveOptions, options: args} 的 action(例如),通常使用 action creator 函数创建,在本例中为 requestOptions()、receiveOptions() 和 fetchOptions。通过 Thunk 中间件,可以编写也可以调度动作的动作创建者。 fetchOptions() 包装在 Promise 中时不能被调度,并且函数不能在没有 dispatch() 的情况下直接调用。我也尝试将 Promise 放入 dispatch => {} 中,但这也不起作用。
  • 好的。为什么 fetchOptions() 包裹在 Promise 中时无法调度?
  • 嗯,可以从一个 thunk 中返回一个 Promise,就像我发现的这个例子:function fetchPosts(subreddit) { return function (dispatch) { dispatch(requestPosts(subreddit)); return fetch(...).then(response => response.json()).then(json => dispatch(receivePosts(subreddit, json)))}} 但我不知道如何将它应用到 ipcRenderer,因为那个函数没有返回一个承诺。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-09
  • 1970-01-01
  • 2017-11-05
  • 2011-02-15
  • 2017-01-17
  • 1970-01-01
相关资源
最近更新 更多