在带有已定义回调函数的JSONP中使用$.when

Using $.when with JSONP with defined callback function

本文关键字:JSONP when 函数 定义 回调      更新时间:2023-09-26

我正在构建一个面板,用户在其中添加贡献者的详细信息,然后输入该贡献者的一个或多个博客的数据。

每个博客都是通过使用JSONP的api调用添加到数据库中的。(请求中需要JSONP回调函数名。)因此,当用户单击AddBlog按钮时,就会调用AddBlog函数——这会进行一些客户端验证并发送ajax请求。它还将ajax请求添加到一个数组中。

回调函数cbAddBlog根据服务器返回的任何错误进行更多验证。

因此,当所有博客都被添加后,我想显示一条消息,让用户知道博客已经保存,并重置表单。

问题是回调函数(cbAddBlog)是在$when..中的代码之后执行的

当您有一个定义的回调函数时,$.when与JSONP一起工作吗?或者我的代码有其他问题吗?我需要在回调函数中实现Deferred吗?

var errorState = false,
    contributorId = '23',
    addBlogCalls = [];
$("#btnAddBlog").click(function (e) {
    $('#add_contributor section.blog').each(function () {       //call addBlog for each of the users blogs
        addBlog(contributorId, $(this).attr('id'));
    });
    $.when.apply($, addBlogCalls).done(function () {
        console.log("WHEN + errorState: " + errorState);  //This is output to console BEFORE the line in the cbAddBlog callback function
    });
    e.preventDefault();
});
addBlog : function (contributorId, blogSection) {
    //client side validation - following is excecuted if there are no errors
    addBlogCalls.push(
       $.ajax({
           url           : (apiRoot + "f=jsonp").trim(),
           dataType      : 'jsonp',
           jsonp         : false,
           jsonpCallback : "cbAddBlog", 
           fail: function (e) {
               console.log("error function");
               console.log(e.message);
           },
           done: function (e) {
               console.log("done function");
               console.log(e.message);
           }
       })
    );
    console.log("Added to addBlogCalls array");
    console.log(addBlogCalls);

}
cbAddBlog : function (data) {
    console.log("cbAddBlog data.result: " + data.result); //Printed to console AFTER line from $.when ??
    //code to check if there are any errors returned from server and display them to user
}

控制台输出:

Added to addBlogCalls array
[Object { readyState=1, setRequestHeader=function(), getAllResponseHeaders=function(), more...}]
Added to addBlogCalls array
[Object { readyState=1, setRequestHeader=function(), getAllResponseHeaders=function(), more...}, Object { readyState=1, setRequestHeader=function(), getAllResponseHeaders=function(), more...}]
WHEN + CD.config.errorState: false
cbAddBlog data.result: 1
cbAddBlog data.result: 1

我看到了同样的问题(即使只有一个博客,回调也会在$.之后执行。

$.when()不接受数组作为参数,它需要一个或多个promise作为单独的参数。因此,如果您有一个数组,则需要使用.apply()将该数组转换为单独的参数。更改此项:

$.when(addBlogCalls)

到此:

$.when.apply($, addBlogCalls)

似乎您对JSONP回调的所有覆盖都阻止了jQuery处理结果,因此它无法解析promise,因此$.when()不起作用。由于您现在已经将服务器更改为接受callback=fname,因此这更容易,因为您可以删除所有特殊的JSONP处理,并让jQuery执行它想要执行的操作。您的代码也可以进行清理,以不依赖于未为后续操作重新初始化的全局。

我推荐这样的东西:

$("#btnAddBlog").click(function (e) {
    var addBlogCalls = $('#add_contributor section.blog').map(function () {       //call addBlog for each of the users blogs
        return addBlog(contributorId, $(this).attr('id'));
    }).toArray();
    $.when.apply($, addBlogCalls).done(function () {
        console.log("WHEN + errorState: " + errorState);  //This is output to console BEFORE the line in the cbAddBlog callback function
    });
    e.preventDefault();
});

addBlog : function (contributorId, blogSection) {
    //client side validation - following is excecuted if there are no errors
    return $.ajax({
           url           : (apiRoot + "f=jsonp").trim(),
           dataType      : 'jsonp'
    }).done(cbAddBlog);
}