JS Q承诺不传播错误

时间:2014-10-06 17:33:44

标签: javascript coffeescript promise q

我正在使用https://github.com/kriskowal/q来创建(深层)嵌套的承诺集。错误不会像我期望的那样传播到最外面的.catch()。请参阅我的coffeescript中的html = tmpl_func(data_)行:

$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内发生的任何错误(例如,如果运行从{{{}}中的脚本标记触发的脚本时出现错误1}}将其发送到html)。

我是否正确使用了承诺?

如何正确处理嵌套承诺中的错误?

我是否误解了replaceWith应该发生什么?

1 个答案:

答案 0 :(得分:1)

您错过了p的重新分配:

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

应该需要

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

否则您只是分支链,但在post_func之后立即执行pre_func