0

I'm building a tool using React and Redux. I'm using whatwg-fetch to make a server side call and fetch some data. And I have a reducer, which will have its store created in a callback, after the data has been successfully fetched. Here is my code:

import {createStore} from 'redux';
import 'whatwg-fetch';

let notificationCardList = [],
    initialState,
    store;

const fetchData = () => {
  fetch('http://localhost:6767/file/data.json')
    .then((response) => response.json())
    .then((responseData) => {
      notificationCardList = Object.keys(responseData).map(key => responseData[key]);
    })
    .then(initializeReducer);
}

const initializeReducer = () => {
  initialState = {
    notifCardsToBeDisplayed: notificationCardList,
    notifCardToBeDisplayed: null
  };

  function manipulateNotificationCards (state = initialState, action) {
    switch (action.type) {
      case 'OPEN_CARD':
        return Object.assign(state, {
          notifCardsToBeDisplayed: null,
          notifCardToBeDisplayed: action.card,
          notifCardsContainerPreviousState: action.notifCardsContainerCurrentState
        });
      case 'DISPLAY_CARD_LIST':
        return Object.assign(state, {
          notifCardsToBeDisplayed: action.cards,
          notifCardToBeDisplayed: null
        });
      default:
        return state;
    }
  }

  store = createStore(manipulateNotificationCards);
}

fetchData();  

export {store, notificationCardList};

But since the store is being created as a part of the callback, due to asynchronous behaviour, the export statement is probably getting executed before the createStore() statement, hence I'm effectively exporting an undefined 'store'. I thought about placing the export statement in the callback as well, but then again, export statements can only be there at the top level. I also tried using setTimeout(), but that didn't work either. Is there any way I can export 'store' after it's created?

1 Answers1

3

The usual scheme for handling asynchronous initialization is to use a module constructor function that gets the desired exported value and that module constructor either returns a promise or takes a callback and the asynchronous exported value is only available via that mechanism. This is because the async operation takes an indeterminate amount of time so the only way a caller can reliably use it is to wait for it to be available via some sort of promise or callback.

A cached promise is a very clean way of doing this. The module initialization stores a promise that will resolve with the desired async value. A module method fetches the promise and the caller then uses .then() on the promise. If the module has not yet finished fetching the async value, then the promise will not call the .then() handler until the value is ready. If the value is already available, then the .then() handler will be called immediately. In either case, the caller just fetches the promise, adds a .then() handler and then acts on the value in the .then() callback.

Some examples of these methods here: How to async require in nodejs

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • The problem is that I can't place the export statement in a callback, as JavaScript doesn't allow that. So my 'store' will always be exported before it's assigned a value. My question is whether I can somehow execute the export statement with a delay, so as to provide time for the callback to be executed. – Rajarshi Chakrabarti Apr 14 '16 at 07:17
  • @RajarshiChakrabarti - I didn't say to put the export in a callback. I said to export a promise or export a function that takes a callback. You cannot do the export statement with a delay. You have to restructure your code so that the caller waits for the value to be ready. And, you can either have the caller pass a callback into a module function and that callback will be called when the value is ready or you have the caller fetch a promise that they can attach a `.then()` handler to that will be called when the value is ready. – jfriend00 Apr 14 '16 at 07:26
  • @RajarshiChakrabarti - Examples here: http://stackoverflow.com/questions/34962075/how-to-async-require-in-nodejs/34962383#34962383 – jfriend00 Apr 14 '16 at 07:28
  • 2
    @coder - It is not appropriate to be asking here for help on a completely unrelated question. That is not cool on stack overflow. – jfriend00 Apr 14 '16 at 07:45
  • @jfriend00: I am really sorry for this, I m so much confused that I m not able to think what should I do. Any suggestion also would be very much appreciated. – Nad Apr 14 '16 at 07:49