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

exercise 9 Juggling Async #467

Open
thekindlyone opened this issue Sep 5, 2016 · 6 comments
Open

exercise 9 Juggling Async #467

thekindlyone opened this issue Sep 5, 2016 · 6 comments

Comments

@thekindlyone
Copy link

After trying a lot of different things, this worked, but I don't fully understand why.

var http = require('http')
var bl = require('bl')
var urls=process.argv.slice(2)
var out = []
var done= 0

for (var i = 0; i < urls.length; i++) {
    http.get(urls[i],function(index){
        return function(response){
            response.setEncoding('utf8')
            response.pipe(bl(function(err,data){
                out[index] = data.toString() 
                done+=1   
                if (done==3){
                    for (var i = 0; i < out.length; i++) {
                        console.log(out[i])
                    }
                }
            }))
        }
    }(i))
}

Why do I have to pass i to the higher order function that returns the callback for http.get but not out and done. done will also be changed asynchronously by the callbacks of response.pipe, and so will out. I feel like I am only partly getting the hang of this async functional stuff. HELP!

@CodeMan99
Copy link

The point of this exercise is to understand that for (var i = 0; i < urls.length; i++) { is a sync control flow tool. The work you are doing however is async.

By async work, I mean that the call to http.get does not block execution. So as you iterate (for loop), the value i will change before the async call finishes.

You avoid this by making a copy of the value:

for (var i = 0; i < 10; i++) {
  (function(index) {
    // index is a copy of "i"
  })(i);
}

You need not copy anything else because the references are not changing while you are iterating.

I struggled with this as well, see #287. My solution is also available as a gist.

More information available from the no-loop-func eslint rule, on mdn, and stack overflow. You should also take the time to learn about Function.bind which can be used to accomplish the same thing.

@thekindlyone
Copy link
Author

Thank you for the links. I will go through them now. Will close if I don't have any further questions.

@AnshulMalik
Copy link
Contributor

Looks like you don't have any further questions :P @thekindlyone

@MeloGuo
Copy link

MeloGuo commented Nov 4, 2017

actually we could use this way to resolve this problem

const http = require('http')
const url = process.argv.slice(2)
let resultQueue = []
let counter = 0

for(let i=0;i<url.length;i++){
    http.get(url[i], function(response){
        let result = ""
        response.setEncoding("utf8")
        response.on("data", function(chunk){
            result += chunk
        })
        response.on("end", function(){
            resultQueue[i] = result
            counter ++
            if(counter == url.length){
                resultQueue.forEach(function(item){
                    console.log(item)
                })
            }
        })
    })
}

I think it's more easy to understand than before

@CodeMan99
Copy link

@MLuka I agree removing the bl dependency is more clear, but that is not the point of the exercise or question. However, the advantage of let vs var is nice since your http.get callback is in the block scope of the let. The let statement has only recently gained popular usage.

For the sake of defensive coding, you should probably still use an IIFE on diverse teams. You don't want a teammate changing that let to var and have everything break. It could lead to a very difficult to track bug.

@MeloGuo
Copy link

MeloGuo commented Nov 5, 2017

@CodeMan99 Thank you for your reminding. I'm still student. Never worked with anyone else.Your words help me a lot!

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