Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any Examples on Async Actions (not really an issue) #26

Open
brownpixel opened this issue May 7, 2017 · 5 comments
Open

Any Examples on Async Actions (not really an issue) #26

brownpixel opened this issue May 7, 2017 · 5 comments

Comments

@brownpixel
Copy link

Hello

Great library. Wondering if there are any examples where you leverage the library's ability to do async actions?..i.e an action where the initiating view can listen to a callback to handle ui changes. Say for instance an action that requires some networking to be achieved and to show/remove a progress indicator while this is being completed

@Yarikx
Copy link
Owner

Yarikx commented May 15, 2017

Hi @brownpixel
That is a good point, hope to find some time and add that topic as a wiki page.

But briefly:
There is no such thing as async action in first place. Each action is synchronous.
However what is usually meant by async actions are in fact just a sequence of them.

A simple example is:

store.dispatch(creator.reload());                    
new Thread(() -> {                                   
    try {                                            
        SomeData data = loadFromNetwork();           
        store.dispatch(creator.dataLoaded(data));    
    } catch (Exception e) {                          
        store.dispatch(creator.dataLoadingFailed(e));
    }                                                
}).start();                                          

What you need to do is to define proper handlers for these three actions (reload, loading succeeded, loading failed). Inside reducer, you know how to manage loading flag or other things based on those actions.

The example above is pretty simple but effective. But I usually prefer to use RxJava to handle all the async work. There is https://github.com/Yarikx/reductor/tree/master/reductor-observable project to do that.

The idea is also simple: You have some Epics that listens to actions, can perform some background work and can dispatch actions back to the Store

Epic<String> pingPongEpic = (actions, store) ->            
        actions.filter(Epics.ofType("PING"))           
                .delay(1, TimeUnit.SECONDS)            
                .map(action -> Action.create("PONG")); 

You can find more information looking for https://redux-observable.js.org/ documentation or examples, as reductor-observable is just a direct port of that approach.

Ask if you need more help.

@colorhaake
Copy link

@brownpixel
I wrote a simple project for reductor.
https://github.com/colorhaake/AndroidReductorTest
This project contains a recycler view for loading random images from imgur.
You can check this out.

@brownpixel
Copy link
Author

@Yarikx @colorhaake Thanks for the replies and suggestions.

I guess you are right in the sense that there is no async actions...was thinking more of an action creator that processes stuff then returns a callback action that runs through the reducer then returns a state. That way you can nicely do some progress dialogs that show/dismiss while this "async" action does its thing...To get an idea you can check out ReSwift's implementation here https://github.com/ReSwift/ReSwift/blob/master/ReSwift/CoreTypes/Store.swift
Specifically their implementation of the AsyncActionCreator

Anyways for now I resorted to RxJava and some state variables that indicate whether things went successfully or not

Thanks again

@Yarikx
Copy link
Owner

Yarikx commented May 28, 2017

@brownpixel If I understood the idea it returns callback when you dispatch an action, am I correct?

If so, similar approach is used in some redux libraries. By default dispatch function returns the same action. But this behaviour can be changed in middlewares. Let's say we can return rx.Single<Result> from dispatch function and rely on it to render progress.

This approach is good enough but it introduces one problem into particular Reductor implementation -- type safety.
In Javascript typing is dynamic, so as long as a developer know what dispatch function can return - he/she can work directly with expected type. You can event return different things for different actions, for instance: promises for async actions and new state for other actions.

In our case, we need to know exactly what dispatch function will return to be able to process the result. But there is no good way to make it expressible without blowing away complexity and diving into generic hell.

Another option is to simply return Object from dispatch function, throwing away type safety. But this will be nowhere near as convenient to use as javascript versions.

For exactly that reason I've made dispatch to return void.

But if you want a bit more fancy action creator you can do it yourself:
write a function that will dispatch an action and then wait for the result to be delivered to some callback or something.
OR
Add some callback as an action parameter. In your middleware you can use it to notify the caller that result was delivered/failed.

@ysyyork
Copy link

ysyyork commented Jun 1, 2017

Is there an easy way to install the epic other than import it as a submodule?

NVM, I found the jcenter repo. Thanks. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants