使用带有JSONP的$ .when和定义的回调函数

时间:2014-09-27 17:25:56

标签: javascript jquery jsonp jquery-deferred .when

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

使用JSONP通过api调用将每个博客添加到数据库中。 (请求中需要JSONP回调函数名。)因此,当用户单击Add Blog按钮时,将调用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

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

1 个答案:

答案 0 :(得分:0)

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

$.when(addBlogCalls)

到此:

$.when.apply($, addBlogCalls)

似乎所有重写JSONP回调都会阻止jQuery处理结果,因此它无法解决承诺,因此$.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);
}