【问题标题】:How to check if a website is up asynchronously?如何检查网站是否异步启动?
【发布时间】:2014-05-13 13:44:10
【问题描述】:

我现在使用两种方法,第一种是通过检查 HTTP GET 状态代码响应来检查网站是否启动:

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

对于第二个,我所做的是从我拥有的一系列网站中选择一个随机站点,并验证(在第一种方法的帮助下)该站点是否已启动。如果是,我想将该站点作为父方法的返回值(在本例中为第二个)返回,但如果不是,我想重新运行该方法,直到它在数组中找到一个在线站点。这是我到目前为止所做的:

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

显然,这不能按我想要的方式工作:如果状态码不是 200,那么它确实会重新运行该方法,(到目前为止,我们还可以);但是当网站确实在线时出现问题,因为我不知道如何将 selected_site 变量(在 checkifUp 调用中声明)作为父级的 返回值方法(在本例中为 siteSet())。我需要这样做才能将 siteSet() 返回值用作另一个函数的变量:

otherFunc = ->
  theSite = siteSet()
  console.log(theSite)

Javascript: http://goo.gl/cmsryJ

并且确信它将始终设置为此 otherFunc()

内的在线站点 URL(字符串)

对此我有两个问题

  1. 我怎样才能在这里完成我想做的事情? (呃,那个很明显呵呵)

  2. 对此我不太确定,但据我所知 Javascript/Coffeescript,当 siteSet() 从内部被调用时 otherFunc(),(至少使用这个“设置”),otherFunc() 不会等到 siteSet() 返回一个字符串(这是我想要的结果) 我对么?即使解决了退货问题,我认为 将会发生的是,当我从内部调用 siteSet() otherFunc() 它将使用调用的确切结果,这意味着如果 siteSet() 运行时它返回 另一个调用 对自己(因为选择的random_site不在线) otherFunc() 中的“theSite”变量将采用裸 function() 作为价值,我正确吗? (如果是这样的话),如何解决这个问题 其他问题?我想在里面设置“theSite”变量 otherFunc() 直到这样的值是我需要的字符串。

提前感谢您的帮助。

【问题讨论】:

  • 您是否尝试将回调传递给 siteSet,就像您对 checkifUp 所做的那样?这就是现在处理异步混乱的方式嘿:)
  • 您有 3 条回复,如果您觉得没有得到很好的回复,请投票给更好的回复或解决您的问题...谢谢..

标签: javascript node.js asynchronous coffeescript


【解决方案1】:

我不太了解 CoffeeScript,所以我正在为您的两个函数使用 javascript 转换。如果 CoffeeScript 中有我不知道的特性,请告诉我。

也就是说,您似乎正在使用异步函数 siteSet,并尝试同步返回值。您可以查看this question 的解决方案以获取更多信息。您有两种有效返回值的选项:

  • 活动
  • 回调

您的第一个函数 checkIfUp 有一个回调,所以我的建议是对 siteSet 也使用一个。您可以按如下方式调用:

otherFunc = ->
  theSite = siteSet ( theSite ) ->
    console.log(theSite)

至少,我认为这是 CoffeeScript 语法。在 JavaScript 中肯定是:

otherFunc() 
{
  theSite = siteSet( function( theSite )
  {
    console.log( theSite );
  } );
}

【讨论】:

    【解决方案2】:

    像使用 checkifUp 一样向 siteSet 添加回调:

    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)
    

    那么你可以这样做:

    otherFunc = ->
      siteSet (theSite) ->
        console.log theSite
    

    【讨论】:

      【解决方案3】:

      这里的问题是,您为 otherFunc 采用同步方法而不是异步方法,让我们检查一下:

         //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()
      

      结果会是这样的:

           resultA is undefined
           calling from funB
           calling from funA
      

      您的代码将被翻译成这样:

        //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
                                                  //
      

      为了更好地理解为什么 nodejs 以这种方式执行代码,请查看这些文章...

      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))
      

      基本上异步代码中的想法(没有承诺,生成器,monads 或其他)比你将你的 functionA 的结果传递给回调......就是这样......

      【讨论】:

        最近更新 更多