{"action":"created","issue":{"url":"https://api.github.com/repos/jeffbski/redux-logic/issues/42","repository_url":"https://api.github.com/repos/jeffbski/redux-logic","labels_url":"https://api.github.com/repos/jeffbski/redux-logic/issues/42/labels{/name}","comments_url":"https://api.github.com/repos/jeffbski/redux-logic/issues/42/comments","events_url":"https://api.github.com/repos/jeffbski/redux-logic/issues/42/events","html_url":"https://github.com/jeffbski/redux-logic/issues/42","id":213716184,"number":42,"title":"Feature Request: waitFor","user":{"login":"shauntrennery","id":98803,"avatar_url":"https://avatars0.githubusercontent.com/u/98803?v=3","gravatar_id":"","url":"https://api.github.com/users/shauntrennery","html_url":"https://github.com/shauntrennery","followers_url":"https://api.github.com/users/shauntrennery/followers","following_url":"https://api.github.com/users/shauntrennery/following{/other_user}","gists_url":"https://api.github.com/users/shauntrennery/gists{/gist_id}","starred_url":"https://api.github.com/users/shauntrennery/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shauntrennery/subscriptions","organizations_url":"https://api.github.com/users/shauntrennery/orgs","repos_url":"https://api.github.com/users/shauntrennery/repos","events_url":"https://api.github.com/users/shauntrennery/events{/privacy}","received_events_url":"https://api.github.com/users/shauntrennery/received_events","type":"User","site_admin":false},"labels":[{"id":417764092,"url":"https://api.github.com/repos/jeffbski/redux-logic/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2017-03-13T09:44:38Z","updated_at":"2017-05-11T08:13:29Z","closed_at":null,"body":"Enhance the validate block with a waitFor option.\r\n\r\nAn example:\r\n\r\nDuring init, an application validates a user's session and populates auth state. Should a redux-logic function depend on auth state but execute prior to auth processes being processed, the validate block can delay execution till a known action is received."},"comment":{"url":"https://api.github.com/repos/jeffbski/redux-logic/issues/comments/300715959","html_url":"https://github.com/jeffbski/redux-logic/issues/42#issuecomment-300715959","issue_url":"https://api.github.com/repos/jeffbski/redux-logic/issues/42","id":300715959,"user":{"login":"tehnomaag","id":1394282,"avatar_url":"https://avatars2.githubusercontent.com/u/1394282?v=3","gravatar_id":"","url":"https://api.github.com/users/tehnomaag","html_url":"https://github.com/tehnomaag","followers_url":"https://api.github.com/users/tehnomaag/followers","following_url":"https://api.github.com/users/tehnomaag/following{/other_user}","gists_url":"https://api.github.com/users/tehnomaag/gists{/gist_id}","starred_url":"https://api.github.com/users/tehnomaag/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tehnomaag/subscriptions","organizations_url":"https://api.github.com/users/tehnomaag/orgs","repos_url":"https://api.github.com/users/tehnomaag/repos","events_url":"https://api.github.com/users/tehnomaag/events{/privacy}","received_events_url":"https://api.github.com/users/tehnomaag/received_events","type":"User","site_admin":false},"created_at":"2017-05-11T08:13:29Z","updated_at":"2017-05-11T08:13:29Z","body":"Just so Jeff has more examples of use-cases this is how I've handled chaining and waiting for other logics to finish.\r\n\r\nThis example is extracted from an e-commerce app that on direct \"buy\" page landing needs to prepare some data (fetch user and product) before it can do other actions. So buy page calls BUY_PREPARE on mounting and that internally delegates to other logics, waits for them to finish and then does it's job in onComplete handler.\r\n\r\nThe pattern is to create and pass `notify` signal channels in `action.meta`, and the logics in question then need to tell this `notify` signal when they are done or if there were errors.\r\n\r\n```js\r\nimport { Observable } from \"rxjs/Observable\";\r\nimport { Subject } from \"rxjs/Subject\";\r\nimport \"rxjs/add/observable/forkJoin\"\r\nimport \"rxjs/add/operator/defaultIfEmpty\";\r\nimport \"rxjs/add/operator/finally\";\r\n\r\nexport const buyPagePrepareLogic = createLogic({\r\n    type: BUY_PREPARE,\r\n    process({ getState, action }, dispatch, done) {\r\n\r\n        const onComplete = () => {\r\n            // safe to use getState here, user and products are loaded\r\n            const user = getState().user;\r\n            const products = getState().producs;\r\n            // ... continue with removing loader screen etc\r\n        };\r\n        const onError = (err) => {\r\n            // logging etc\r\n        };\r\n\r\n        // defaultIfEmpty guards against empty complete stream\r\n        // from short-circuiting forkJoin below\r\n        const userSignal = new Subject().defaultIfEmpty(true);\r\n        const productSignal = new Subject().defaultIfEmpty(true);\r\n\r\n        Observable\r\n            .forkJoin([userSignal, productSignal])\r\n            .finally(done)\r\n            .subscribe(null, onError, onComplete);\r\n\r\n        // null payload in this case but set action.meta.notify\r\n        dispatch(FETCH_USER(null, { notify: userSignal }));\r\n        dispatch(FETCH_PRODUCTS(null, { notify: productSignal }));\r\n    }\r\n});\r\n\r\nexport productFetchLogic = createLogic({\r\n    type: FETCH_PRODUCTS,\r\n    process({ action }, dispatch, done) {\r\n        const { notify } = action.meta;\r\n\r\n        api\r\n            .getPrducts()\r\n            .then((res) => {\r\n                dispatch(PRODUCTS_LOADED(res.products));\r\n                notify.complete();\r\n            })\r\n            .catch((err) => {\r\n                // log error and..\r\n                notify.error(err);\r\n            })\r\n            .then(done);\r\n    }\r\n});\r\n\r\nexport userFetchLogic = createLogic({\r\n    type: FETCH_USER,\r\n    process({ action }, dispatch, done) {\r\n        const { notify } = action.meta;\r\n\r\n        api\r\n            .getUserProfile()\r\n            .then((res) => {\r\n                dispatch(USER_LOADED(res.user));\r\n                notify.complete();\r\n            })\r\n            .catch((err) => {\r\n                // log error and..\r\n                notify.error(err);\r\n            })\r\n            .then(done);\r\n    }\r\n});\r\n```"}}
{"actor":{"display_login":"tehnomaag"}}