2014-10-06 36 views
0

我使用https://github.com/kriskowal/q創建(深)嵌套的承諾集。錯誤不會按照我期望的方式傳播到最外面的.catch()。見html = tmpl_func(data_)線在我的CoffeeScript:JS Q保證不傳播錯誤

$exp.setEventResponse = (event_str, pre_func, tmpl_list, post_func) -> 
    $(document).on(event_str, (_event, args) -> 
     console.log("on: #{event_str}. #{args}") 

     data = args or {} 
     data._start_ts = now = Date.now() 
     data.trigger = $exp.trigger 
     #return data 

     p = Q(data) 

     if pre_func 
      p = p.then((data_) -> 
       pre_func(data_) 
      ).then((data_) -> 
       if data_._start_ts != now 
        throw new Error("#{event_str}_pre must return data or Q(...).then(() -> data)") 
       return data_ 
      ) 

     p.then((data_) -> 
      pp = Q(data_) 
      if tmpl_list or data_.extraTmpl_list 
       console.log(tmpl_list.concat(data_.extraTmpl_list or [])) 
       for tmpl_args in tmpl_list.concat(data_.extraTmpl_list or []) 
        closure_func = (ppp, tmpl_args) -> 
         return ppp.then((data_) -> 
          if tmpl_args.length == 3 
           [selector, tmpl_func, replace] = tmpl_args 
          else 
           [selector, tmpl_func] = tmpl_args 
           replace = true 
          try 
           html = tmpl_func(data_) 
          catch error 
           console.log error 
           throw error 

          if replace 
           $(selector).replaceWith(html) 
          else 
           $(selector).html(html) 

          return data_ 
         ) 
        pp = closure_func(pp, tmpl_args) 

       pp = pp.then((data_) -> 
        if data_._start_ts != now 
         throw new Error("#{event_str}_tmpl must return data or Q(...).then(() -> data)") 
        return data_ 
       ) 

      return pp 
     ) 



     if post_func 
      p = p.then((data_) -> 
       post_func(data_) 
      ).then((data_) -> 
       if data_._start_ts != now 
        throw new Error("#{event_str}_post must return data or Q(...).then(() -> data)") 
       return data_ 
      ) 

     p.then((data_) -> 
      data_._end_ts = Date.now() 
      duration_sec = (data_._end_ts - data_._start_ts)/1000.0 

      if duration_sec >= _durationLogThreshold_sec 
       console.log("Event #{event_str} duration: #{duration_sec} sec") 

      return data_ 
     ).catch((reason) -> 
      console.log(reason) 
      #alert(reason) 
     ).done() 
    ) 

調用,像這樣:

$exp.setEventResponse('showScan', 
    showScan_pre, [['#content', showScan_tmpl]], showScan_post) 

如果tmpl_func引發錯誤就不會觸發.catch((reason) ->附近的片段結束。我希望能夠處理髮生在closure_func內部的任何錯誤(例如,如果運行腳本時發生錯誤,該腳本在發送到replaceWith時由html中的腳本標記觸發)。

我是否正確使用承諾?

如何正確處理來自嵌套promise的錯誤?

我誤解了catch應該發生什麼?

+0

嘿,你可以嘗試http://pastebin.com/LNU3WTUT - 這是更多的「coffeescript」國際海事組織,並做同樣的事情 - 這是否適合你? – 2014-10-06 18:05:03

+1

爲什麼你要求'pre_func'和'post_func'返回'data'?或者你是否期望他們只用'_start_ts'設置爲相同的值來返回數據的副本? – Bergi 2014-10-06 18:12:47

+0

本傑明Gruenbaum:這似乎是合理的,但我必須等到今晚才嘗試。感謝重構;我擁有的是相當醜陋的。 – 2014-10-06 18:54:46

回答

1

你缺少一個重新分配到p

p.then((data_) -> 
    pp = Q(data_) 
    … 
    return pp 
) 

應該必須

p = p.then((data_) -> 
    pp = Q(data_) 
    … 
    return pp 
) 

否則你只是分支鏈,但pre_func後立即執行post_func

+0

聽起來正確 – 2014-10-06 18:10:09

+0

謝謝,這看起來像是我做錯了。一旦我不在工作,我會測試並接受今晚。 – 2014-10-06 18:55:40