Reputation: 6686
I have two methods I'm using right now, the first one is to check if a website is up or not, by checking the HTTP GET status code response:
checkifUp = (host, callback) ->
host = host.replace("http://", "").replace("/", "")
options =
host: "#{host}"
port: 80
path: "/"
req = http.get(options, (res) ->
callback(res.statusCode.toString())
req.connection.destroy()
)
Javascript: http://goo.gl/OyekSx
And with the second one, what I do is to select a random site from an array of websites I have and verify (with the help of the first method) if such site is up. If it is, I wanna return the site as the return value of the parent method (in this case the second one), but if it is not, I wanna re-run the method until it finds an online site in the array. This is what I have done so far:
siteSet = ->
site_urls = ["sub1.mysite.com", "sub2.mysite.com", "sub3.mysite.com", "sub4.mysite.com", "sub5.mysite.com"]
random_site = site_urls[Math.floor(Math.random()*site_urls.length)]
checkifUp "#{random_site}", (code) ->
if code isnt "200"
siteSet()
else
selected_site = random_site
selected_site
Javascript: http://goo.gl/ydmSiV
Obviously, this doesn't work the way I want: if the status code isn't 200, then it re-runs the method indeed, (so far, we're ok); But the problems appear when the site is indeed online as I don't know how to return the selected_site variable (declared inside the checkifUp call) as the return value of the parent method (in this case siteSet()). I need to do this in order to be able to use the siteSet() return value as a variable for another function:
otherFunc = ->
theSite = siteSet()
console.log(theSite)
Javascript: http://goo.gl/cmsryJ
And be confident it will always be seted to an online site URL (string) inside this otherFunc()
I have two questions about this:
How can I accomplish what I wanna do here? (Duh, that one it's obvious hehe)
I'm not quite sure about this, but as far as I understand Javascript/Coffeescript, when siteSet() gets called from within otherFunc(), (at least with this "setup"), the otherFunc() won't wait until siteSet() returns a String (which is the result I want) am I correct? Even with the return problem solved, what I think is going to happen is that when I call siteSet() from within otherFunc() it will use the exact result from the calling, this means that if when siteSet() gets runned it returns another call to itself (because the random_site chosen was not online) the "theSite" variable inside otherFunc() will take the bare function() as value, am I correct? (and if that's the case), how to solve this other problem? I want to set the "theSite" variable inside of otherFunc() until such value is a String as I need it to.
Thanks in advance for any help.
Upvotes: 0
Views: 1105
Reputation: 2324
the problem here is than you're taking a sync approach for your otherFunc instead of the async one, let's ckeck this:
//sorry I prefer use plain js, I'm pretty sure than you will be able to understand the code
var funA = function(){
//long computation here
console.log("calling from funA");
}
var funB = function(){
var resultA = funA();
console.log("resultA is " + resultA);
console.log("calling from funB");
}
funB()
the result would be something like this:
resultA is undefined
calling from funB
calling from funA
your code would be translate to this:
//sorry I'm not so familiar with coffeescript so maybe I would do a little mistake
siteSet = (callback)->
site_urls = ["sub1.mysite.com", "sub2.mysite.com", "sub3.mysite.com", "sub4.mysite.com", "sub5.mysite.com"]
random_site = site_urls[Math.floor(Math.random()*site_urls.length)]
checkifUp "#{random_site}", (code) ->
if code isnt "200"
siteSet()
else
selected_site = random_site
callback(selected_site)
otherFunc = ->
siteSet((result)-> console.log(result)) //(result)-> console.log(result) is your
//callback, so inside checkifUp you will call it and pass selected_site
//
for better understand of why nodejs execute the code in this way check these articles...
http://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks
http://dreamerslab.com/blog/en/javascript-callbacks/
x = LONGIO()
console.log(x)
vs
LONGIO((resultOfLongIO)-> console.log(resultOfLongIO))
basically the idea in async code (without promise,generators,monads or whatever) is than you pass the result of your functionA to the callback...that is all...
Upvotes: 1
Reputation: 3194
Add a callback to siteSet just like you did with checkifUp:
siteSet = (callback) ->
site_urls = ["sub1.mysite.com", "sub2.mysite.com", "sub3.mysite.com", "sub4.mysite.com", "sub5.mysite.com"]
random_site = site_urls[Math.floor(Math.random()*site_urls.length)]
checkifUp "#{random_site}", (code) ->
if code isnt "200"
siteSet()
else
callback(random_site)
Then you can do:
otherFunc = ->
siteSet (theSite) ->
console.log theSite
Upvotes: 0
Reputation: 26
I don't know CoffeeScript that well, so I'm using the javascript conversions for your two functions. If there are idiosyncrasies in CoffeeScript that I'm not aware of, please let me know.
That said, it looks like you're using an asynchronous function, siteSet, and trying to return a value synchronously. You can check the solutions to this question for more information. You have two options for returning values effectively:
You have a callback for your first function, checkIfUp, so my recommendation is to use one for siteSet as well. You could invoke as follows:
otherFunc = ->
theSite = siteSet ( theSite ) ->
console.log(theSite)
At least, I think that's the CoffeeScript syntax. In JavaScript it's definitely:
otherFunc()
{
theSite = siteSet( function( theSite )
{
console.log( theSite );
} );
}
Upvotes: 0