【问题标题】:JavaScript Promise .then() and .catch firing at the same timeJavaScript Promise .then() 和 .catch 同时触发
【发布时间】:2019-01-12 03:35:45
【问题描述】:

我正在将我在 wordpress 上的 cmets 变成一个 ajax 驱动的系统。

到目前为止一切都很好,直到我遇到了 .catch() 方法在 .then() 方法之后直接触发的问题。

这是我的代码...

Ajax 引擎

commentAPI: function(action, encoded, userID) {
    let self = this;

    return new Promise(function (resolve, reject) {
       //console.log("ajax call to " + self.ajaxURL + " with action " + action);

        jQuery.ajax({               
            url: self.ajaxURL,
            type: 'post',
            data: 'action='+action+'&data='+encoded,
            dataType: 'json',
            success: function(data, code, jqXHR) { resolve(data); },
            fail: function(jqXHR, status, err) { console.log('ajax error = ' + err ); reject(err); },
            beforeSend: function() {} //display loading gif
        });
    });
}, 

处理评论表单提交的方法

handleReplyFormSubmit: function(form) {
    let self = this;

    this.removeErrorHtml(form);

    // Serialize form to name=value string
    const formdata = jQuery(form).serialize();

    // Validate inputs
    // * Wordpress doing this for now and providing error resonse 

    // Encoode data for easy sending
    const encodedJSON = btoa( formdata );

    this.commentAPI('dt_submitAjaxComment', encodedJSON).then(function(response){
        console.log('firing then');

        if( response.error == true ) {
            self.printFormError(form, response.errorMsg);
        }

        else { 
            let html = response.commentHTML;
            console.log('html returned' + html)
            jQuery(form).append(html);
            Jquery(form).remove();
        }

    }).catch(function(err) {            
        console.log('firing catch');

        if( err !== undefined && err.length > 0 ) { 
            self.printFormError(form, err);
        }

        else { 
            self.printFormError(form, 'Unkown error');
        }
    });

    return false;
},

代码正在做它应该做的事情,但是 catch 方法也被触发了,这使得错误处理令人沮丧......

注意它是如何被触发的

console.log('firing catch')

但这不是(在 ajax 失败函数中)

console.log('ajax error = ' + err );

我做错了吗?

【问题讨论】:

    标签: javascript ajax


    【解决方案1】:

    承诺

    then 触发是很常见的,然后是 catch:这意味着您的 then 处理程序代码中遇到了一些错误,因此 catch 触发。 Catch 处理程序将触发:

    • 如果异步操作出错,则 Promise 被拒绝。
    • 如果之前的任何 then 处理程序中有错误。

    所以,下面的代码:

    Promise.resolve()
    .then( () => {
      console.log('this will be called');
      throw new Error('bum');
      console.log('this wont be logged');
    })
    .catch(err => {
      console.log('this will be logged too');
      console.log(err); // bum related error
    });
    

    将产生来自thencatch 处理程序的日志。

    您的代码

    在您的 then 处理程序中有以下代码:

        else { 
            let html = response.commentHTML;
            console.log('html returned' + html)
            jQuery(form).append(html);
            Jquery(form).remove();
        }
    

    注意最后一行是Jquery 而不是jQuery,这是一个错字。我敢打赌这是导致catch 触发的错误。

    最重要的是

    现代版本的 jQuery 只返回一个来自 $.ajax() 的 Promise,因此无需将其包装到另一个 Promise 中。

    这段代码:

    commentAPI: function(action, encoded, userID) {
      let self = this;
    
      return new Promise(function (resolve, reject) {
      //console.log("ajax call to " + self.ajaxURL + " with action " + action);
    
        jQuery.ajax({               
            url: self.ajaxURL,
            type: 'post',
            data: 'action='+action+'&data='+encoded,
            dataType: 'json',
            success: function(data, code, jqXHR) { resolve(data); },
            fail: function(jqXHR, status, err) { console.log('ajax error = ' + err ); reject(err); },
            beforeSend: function() {} //display loading gif
        });
      });
    },
    

    应该是:

    commentAPI: function(action, encoded, userID) {
        return jQuery.ajax({
            url: this.ajaxURL,
            type: 'post',
            data: 'action='+action+'&data='+encoded,
            dataType: 'json',
            beforeSend: function() {} //display loading gif
        });
    },
    

    因此您可以在 commentApi thencatch 处理程序中处理成功和失败,而不是通过 successfail 回调来解决或拒绝包装的 Promise。

    ajax 成功参数

    success 回调参数采用三个参数。然而,Promises通常只需要一个。

    但是,jQuery 确实将相同的三个参数传递给then 处理程序,所以如果您需要访问它们,您仍然可以在处理程序中使用它们:

    this.commentAPI('dt_submitAjaxComment', encodedJSON).then(function(data, code, jqXhr){
     // the three arguments will be accessible here.
    ...
    }
    

    【讨论】:

    • 谢谢,在您回复之前我确实看到了错字,但它确实修复了它。为什么错误只是“未定义”?我还应该在 catch 中检查另一种类型的错误对象吗?
    • 同样当你建议减少commentAPI时,哪些参数被传递给promise resolve/reject回调?与我在 ajax 函数中列出的默认值相同?
    • “可能只是”应改为“应该只是”以避免explicit promise construction antipattern
    • 您不需要传递参数,您可以在 ajax 调用之后立即调用 thencatch。我稍后会用一个例子更新我的答案。
    • 不过你可能想use Promise.resolve(…)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2020-03-12
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多