Generalize Effect Handling with Drivers in the run() Function

André Staltz
InstructorAndré Staltz

Share this video with your friends

Send Tweet
Published 6 years ago
Updated 3 years ago

The last part of the code we wrote is neither logic nor effects. It is code which ties together logic (main) with effects. We can encapsulate that in a run() function. This lesson shows how we can structure these pieces together, and generalize effect handling with "drivers".

[00:00] Our application now has some clear structure. We have main for logic, and we have some driver functions for effects. This part down here is neither logic nor effects. What it does is tie together the main with the drivers. Essentially, it is meant to make our app just run.

[00:17] We could put that in a function called run, and that takes as argument the main function. Then here, we just call that main function like this to get the sinks, and then pass those to the drivers.

[00:33] Now, this works after we pass our actual main function, that one up there, to run. Then it would work just like before. One problem is that here, we have the drivers hard-coded into this run so it's not so generic.

[00:50] One of the problems is that if you just don't have the log anymore, then sinks.log would be undefined. Then once we try to pass undefined to this log driver, it would try to subscribe to something undefined, and it would crash.

[01:05] It's not nice that we're hard-coding it here. Instead, what we can do is pass those drivers here as an argument. We're basically saying run this application and use these drivers to execute those effects. For instance, this would be an object, and here we would have the DOM driver and the log driver.

[01:25] Under the key DOM, we can put the DOM driver, and under the key log, we can put the log driver so that this key will match the key there, and this key here in the drivers object will match the key there in the sinks object.

[01:44] Now that this is an object, we can iterate over each key by doing object.keys. For each key, we can run a piece of code. First, we want to actually check does sinks under that actually exist? Here for log, it won't exist, so sinks.log will be undefined, and we don't want to run the log driver in that case.

[02:13] We only want to run it if it's not undefined, so if it's a normal situation. In that case, we are going to say drivers key. Let's say in the case of log, that would be drivers.log, and we're going to pass the corresponding sink.

[02:33] Then we don't need this anymore. Once we run this function, it's going to check under each of these properties, does it have a sink corresponding to it? If it does, it's going to pass it to this function and so forth.

[02:48] This should still work like before, except now we don't have the console effect, because we have turned that off here in main. We can put that back, and then run our application again. Now, we see both of the effects happening as it should.

[03:05] This is how run can become very generic, and we don't need to hard-code anything inside it anymore. Its only role is to plug together the main function with the drivers.

Samuel Sharpe
Samuel Sharpe
~ 6 years ago

If you comment out Log: from main(), it will still throw an error. I think run() would need to check the keys before running each effects https://jsbin.com/fahazihahe/1/edit?html,js,console,output?

André Staltz
André Staltzinstructor
~ 6 years ago

Samuel, correct! That if statement slipped from me when recording, and the program still executed. However, we quickly introduced the official Cycle.run(), which I mentioned has enough error checks. The point of this lesson is to understand what run() is responsible for.

Adam Barrett
Adam Barrett
~ 6 years ago

So close to calling it Log Driver https://www.youtube.com/watch?v=upsZZ2s3xv8 ...so close