JavaScript承诺.then()和.catch同时触发

Dal*_*ods 4 javascript ajax

我正在将关于wordpress的评论转变为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
        });
    });
}, 
Run Code Online (Sandbox Code Playgroud)

处理评论表单提交的方法

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;
},
Run Code Online (Sandbox Code Playgroud)

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

输出代码. 请注意,正在触发console.log('fired catch')

注意这是如何被解雇的

console.log('firing catch')
Run Code Online (Sandbox Code Playgroud)

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

console.log('ajax error = ' + err );
Run Code Online (Sandbox Code Playgroud)

难道我做错了什么?

Ser*_*eon 6

承诺

通常会发生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
});
Run Code Online (Sandbox Code Playgroud)

将从thencatch处理程序生成日志.

你的代码

你的then处理程序里面有这样的代码:

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

注意最后一行是如何Jquery代替的jQuery,这是一个错字.我打赌这是导致catch火灾的错误.

最重要的是

jQuery的现代版本只返回一个promise $.ajax(),因此不需要将它包装到另一个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
    });
  });
},
Run Code Online (Sandbox Code Playgroud)

应该只是:

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
    });
},
Run Code Online (Sandbox Code Playgroud)

因此,您可以处理成功和失败commentApi then以及catch处理程序,而不是传递successfail回调来解决或拒绝包装Promise.

ajax的成功助手

success回调PARAM有三个参数.然而,Promises 通常只需要一个.

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

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

  • "可能只是"应该读"应该只是"以避免[显式承诺构建反模式](/sf/ask/1666262041/怎么办-I-避免-IT) (2认同)