Flux waitFor() and async operation, how to model.
Asked Answered
A

1

7

I'm using pouchDB as a local database for an app. I want to query the results from PouchDB and load this into React.js. However, even though I'm using the waitFor() method the results of PouchDB query return too late. I think I don't understand the use of waitFor() correct, maybe someone can shed a light on it.

I have two stores, the DbStore that retrieves data from the datbase. And the FileExplorerStore this store is used by my react components.

DbStore.dispatchToken = AppDispatcher.register(function (payload) {

    var action = payload.action;
    var folder = payload.action.folder
    switch (action.type) {

        case 'OPEN_FOLDER':    
            if (folder === 'start') {
                DbStore.init();
            }
            else {
                DbStore.createPath(folder);
            }
            DbStore.emitChange();
            break;
        default:
        // do nothing
    }


    return true;
});

The DbStore has a function LoadFiles that will load the DB files into the _files array. For illustrative purposes I've copied the code below:

loadFiles: function (_path) {
            var fileNames = fs.readdirSync(_path);
            _files = [];


            fileNames.forEach(function (file) {
                console.log(file)
                db.query(function (doc) {
                    emit(doc.name);
                }, {key: "bower.json"}).then(function (res) {
                    _files.push(res.rows[0].key)
                });
            });

 }, 

The FileExplorerStore had a method to retrieve the files from the _files array. Then in the FileExplorerStore I have a getFiles() method, that will retrieve these files. However, this array is always empty because this method will be executed before the array is filled.

FileExplorerStore

FileExplorerStore.dispatchToken = AppDispatcher.register(function (payload) {

var action = payload.action;


switch (action.type) {

    case 'OPEN_FOLDER':
        AppDispatcher.waitFor([DbStore.dispatchToken]);

        FileExplorerStore.emitChange();
        break;
    default:
    // do nothing
}


return true;
});

In react.js the getInitialState function will call the getFiles() function from the FileExplorerStore to display the files.

How can I fix this or model this in a better way?

Aranda answered 5/1, 2015 at 18:56 Comment(0)
B
9

The waitFor in the dispatcher released by the Facebook team was not designed for that (at least the release on Sep 11, 2014), it just make sure the dispatchToken (which passed to waitFor) was executed and returned, and then it will starts executing the next registered callback.

So in your case this is somehow the correct expected behaviour.

What i will do is separate the action into two parts. First is fetching, second is OPEN_FOLDER as in FileExplorerStore. Assuming the DBfetch action named DB_FETCH, this will trigger your database and then get the data into _files, in the fetch success callback, trigger an action to the OPEN_FOLDER. For the trigger point, it is depends on you how you want to design it, i would have the third action named INIT_OPEN_FOLDER which trigger the DB_FETCH, then show the loading indicator to the UI, and finally when get the emit from OPEN_FOLDER, only display the data

Bushwhacker answered 6/1, 2015 at 11:14 Comment(2)
Thanks. It seems like your explanation is the right way to model this. I also checked the #reactjs IRC and they also advices to call an action in my Async fetch callback. I did however changed to Reflux because in Reflux I can call my Database API from Actions, and after the data is fetched execute the next action.Aranda
@Bushwhacker may you look here pls #32538068Chaker

© 2022 - 2024 — McMap. All rights reserved.