Rethinking Asynchronous JavaScript

Exercise 6 Solution

Kyle Simpson

Kyle Simpson

You Don't Know JS
Rethinking Asynchronous JavaScript

Check out a free preview of the full Rethinking Asynchronous JavaScript course

The "Exercise 6 Solution" Lesson is part of the full, Rethinking Asynchronous JavaScript course featured in this preview video. Here's what you'd learn in this lesson:

Kyle walks through the solution to exercise 6.

Preview
Close

Transcript from the "Exercise 6 Solution" Lesson

[00:00:00]
>> [MUSIC]

[00:00:03]
>> Kyle: So I'm now going to open an exercise four fixed version on this side and I'm going to open up exercise 6. And again, show you the side by side way of dealing with ex6. So, we still have our same get file the way we did with ex5.

[00:00:29]
But how are we going to handle this map reduce thing. Well, I'm gonna start with a list of "file1", "file two", "file three", okay? Now I'm still going to do a .map call and call .map, this is the array map. Plain old normal array pass it getFile. And the end of that I now have an array of sequences.

[00:00:58]
Does everybody catch that it's not an array of Promises anymore. It's an array of async sequences. And I want to turn those sequences into something that I can chain into a sequence. So I could do a .reduce call here and take the exact same approach of chaining things in with .seq and .val.

[00:01:18]
So I could do exactly the same thing I did in EX-4 and it would work exactly the same way. But there's an even easier way of doing it by recognizing the fact that one of the virtues again of a Promise library giving you some extra sugar if you will.

[00:01:34]
One of the sugars is that the asynquence methods at least some of the methods. Many of the methods will receive multiple items as if you called the thing multiple times. So with .seq I can pass multiple sequences into it and I don't have to call seq once for each sequence.

[00:01:53]
I can pass multiple sequences into it. So if I have this set of sequences here. I could just pass them directly into a .seq call. Now unfortunately, it's not as simple as that, because seq doesn't take a raise, cuz there's no way to know whether or not you want that array to be a value or whether you want it to be an array of sequences.

[00:02:18]
So it's not polymorphic in that sense but with the ES6 all we need is the dot dot dot to spread out in array. So we are spreading out an array of sequences.
>> Kyle: But there's one last little detail here, which is we're not sequencing in those outputs yet are we?

[00:02:54]
So we could sequence in the outputs into these individual sequences by recognizing that another transformation needs to occur as I need to take each single step sequence and turn it into a two step sequence. A sequence of waiting for the event, waiting for the text and printing it.

[00:03:12]
So I'm gonna do another .map call, not to reduce but another .map call which takes a sequence. I'll call it sq just for shortness and clarity. It takes a sequence and needs to do a transformation on it, right? What's our transformation?
>> Kyle: That would be a transformation. That will push that sequence into the bigger sequence and push it into the bigger sequence and push it into the bigger sequence.

[00:03:51]
To make that further clear we're going to pass these as a set of functions in this isn't strictly necessary but now this is a set of functions being pushed into the seq so that they will be called at the appropriate time, okay? So this would they should work without the function wrapper here but just to make it clear we can turn this into a array of functions that produce a sequence.

[00:04:20]
That's what sequenced traditionally expects. Or we can just simply turn it into an array of sequences.
>> Kyle: And what's gonna happen if, actually, so let me back up. So what's gonna happen if we turn this into an array of independent sequences is that we might get file2 printed before file1 because these are still independent sequences.

[00:04:43]
The way we make them dependent is to defer with the function wrappers and that was the purpose for the function, okay? We've turned an array of strings into an array of sequences and then we turn an array of sequences into an array of functions that will return those sequences.

[00:05:07]
>> Speaker 2: My question is can we not implement that previous one with the same map and defer it when we print the output.
>> Kyle: The problem with Promises, the reason why that technique doesn't work over here with Promises, is that they can't accept multiple functions. Asynquence can accept multiple functions and it knows what to do with it.

[00:05:28]
But you can't do that over here, so you actually have to manually chain them together which is why we need to the reduce call. Reduce may work better for your brain and if so that's great, you can do that with asynquence. But I'm just trying to show you that we can get rid of the complexity of reduce and simply do two map calls.

[00:05:45]
Taking advantage of the fact that we can access receive an array of functions. Did I lose everybody? Can I get a thumbs up if it's making at least half sense, okay, right. I get that there's a little bit of complexity here. Nothing that I'm presenting to you should be like immediately you're a master on it.

[00:06:11]
This is all presenting you stuff that it's giving you the inspiration to go dig and learn these things and practice them. There's no substitute for the practice to get to the point where the stuff is comfortable, okay?
>> Kyle: All right, so that's exercise five and six our next topic of discussion.

[00:06:37]
My last point to make. If you want to know more about asynquence, more than even the documentation, I wrote two or three part blog series on it and you can read more about asynquence and its design principles and ways to think about using it. So if you're interested in learning more be my guest.

[00:06:55]
Feel free to read about them. Over the break, there were several questions where it felt like I might have created a little bit of confusion at the end of our discussion on ex6, exercise 6. So I wanted to circle back to that and make sure I was a little bit clear.

[00:07:10]
That way, we didn't leave the confusion around it. At the outset, let me say that everything that we're about to discuss is really more about JavaScript and much less about asynquence. So this isn't some complexity about asynquence. It's just understanding the mechanisms that are are happening in JavaScript.

[00:07:27]
But what I've done is I've sketched out what we were originally talking about, which was over here on the right, you can see that I'm returning directly the sequence with the val output put onto it. So any time you're having trouble picturing or understanding or sussing out what a map or map and reduce or whatever it is doing.

[00:07:50]
I encourage you to unroll that in your mind at least unroll a few steps of it in your mind even type it out that way you have a clearer picture of what's happening. [COUGH] So what I've done is do that over here on the left. I've unrolled what was happening over there on the right when we directly returned the sequence and val output.

[00:08:09]
You notice that I start out with an array of strings. This map call changes it into an array of sequences. This map call changes it into an array of other sequences. Sequences which have .val and output but there are still three independent sequences, which means they're going to be able to independently proceed and independence is not what we want here.

[00:08:30]
We're trying to create dependence between them so that they sequence correctly. So if we visualize what's happening over here on the left, you can see that on it's like passing in three independent sequences. So each one of those is able to go to its output as soon as it finishes, which means we're not coordinating the s1 output to happen before the s2 output before the s3 output.

[00:08:52]
That's really all JavaScript, that's got nothing to do with asynquence. It's just that these things these three things are independent right now. And we want them to be dependent. Also to point out this dot, dot, dot. Its happening after we've produced an array so I went ahead and put in the wrapping parentheses here to make it clear that dot dot dot being used here is spreading out an array.

[00:09:16]
So we started out with an array and we spread it out as a series of actual arguments. If the .seq method took an array. Then everything that we did over here would be exactly the same except we'd take out the... Sequence doesn't take an array because there's no way polymorphically to know whether or not you intend that to be a single value passed through or whether you intend it to be an array of values to be interpreted.

[00:09:41]
So because of that I said earlier, I don't like polymorphism I don't like confusing conventional polymorphism. So it's just not polymorphic in that way. Meaning you can't pass on an array. You have to pass them in separately. The old school way as you'll see in the solution files to use that apply.

[00:09:59]
I'm trying to help you understand how ES6 helps makes these things clear. So that's a spreading out an array and it should be clear now that, that's why this is not sufficient, cuz these are three independent sequences that will output independently, and that's not what we want. So if we go back to where we did end up, which is that we're returning a function that returns those sequences.

[00:10:21]
Then the equivalent of what's happening when we unroll it is that there are three independent functions being passed in. So what we've done is start with an array of strings produce an array of sequences and now we're mapping that to an array of functions. And then we of course dot dot dot spread out the array of functions as individual function arguments.

[00:10:42]
So I have a function here, a function here, and a function here. Now we do need to understand something specific about how asynquence works. It shouldn't be confusing but it's something we should call out specifically. And that is that most of the methods that take one or more functions.

[00:11:00]
If you pass two or three functions like we're passing three functions here. The API will run the first function and then go on to the second function only after the first one finished and so forth. So does everything serially. So these three functions even though they're being passed into the same sequence method are still going to run this one entirely to its completion, which means wait for that sequence to finish.

[00:11:23]
And then, run this function and run that sequence entirely to completion. And then, this function and that sequence entirely to completion. So that is the way to unroll what we've produced over here on the right-hand side, is that we've created a list of functions and spread those functions out to the sequence call.

[00:11:40]
And this, if that's confusing passing multiple functions into .seq, you can also alternatively visualize that as three separate .seq calls.
>> Kyle: So hopefully that makes it clearer. But each one of those is going to happen in sequence, serially. Hopefully, that cleared up some of the confusion that we might have wrought by trying to go through quickly the throwaway parts of the solution for exercise six, and it makes it more clear why we ended up over here.

[00:12:17]
And again just to refrain. The vast majority of that is understanding using JavaScript mechanisms. It has very, very little to do with asynquence itself. The only part that's asynquence specific is that it expects individual values and it will do them serially.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now