【问题标题】:Using $.when with JSONP with defined callback function使用带有定义回调函数的 JSONP 使用 $.when
【发布时间】:2014-11-22 12:14:24
【问题描述】:

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

每个博客都通过使用 JSONP 的 api 调用添加到数据库中。 (请求中需要 JSONP 回调函数名称。)因此,当用户单击“添加博客”按钮时,会调用 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 之后执行,即使只有一个博客..

【问题讨论】:

    标签: javascript jquery jsonp jquery-deferred .when


    【解决方案1】:

    $.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);
    }
    

    【讨论】:

    • 谢谢你 - 非常感谢 - 我已经在我的代码中更新了它。但是现在它根本没有执行 when 部分中的代码。这可能与这是 JSONP 的事实有关吗?我在其他地方对 JSON 调用使用了类似的代码,它运行良好——一旦调用完成,它就会在 $when 中执行代码。
    • @user1492058 - 一般来说,为 jQuery JSONP 调用指定自己的回调函数是一件坏事,因为您将 jQuery 从响应循环中删除,因此它无法执行正常情况下执行的操作收到响应(例如解决承诺或调用完成回调)。所以,这可能就是你没有得到任何已解决的承诺的原因。
    • @user1492058 - jQuery 文档的这一部分不是很清楚,但是如果您的服务器在 URL 中需要 cb=xxx 而不是 callback=xxx,那么应该有一种方法告诉 jQuery更改回调参数的名称,但仍然让它提供自己的函数,以便它可以完成所有正常的响应处理。我阅读文档的第一个猜测(在这方面写得不好)是您可以为$.ajax() 设置jsonp: 'cb' 选项,将cb=cbAddBlog 从URL 中取出,然后在普通的jQuery 中处理ajax 响应地方,也许在$.when()的末尾。
    • 谢谢你。我刚刚更新了上面的代码。从文档(api.jquery.com/jquery.ajax)看来,我需要将 jsonp 设置为 false 并在 jsonpCallback 参数中添加函数名称。它仍然没有起作用。响应返回包装在一个名为“回调”的函数中,并且它没有到达 ajax 中的失败或完成函数。在 $.when 末尾添加回调代码是行不通的 - 我只希望在所有 addBlog 调用完成后执行 $.when 中的代码 - 可能有多个调用来添加博客数据贡献者..
    • @user1492058 - 我不确定你是否理解我所描述的问题。如果你为 JSONP 调用(你正在做的)提供你自己的回调函数,那么 jQuery 不会处理响应。没有调用 ajax 回调,也没有解决任何承诺。 jQuery 甚至从未被告知响应。因此,您不会从 jQuery 中获得任何关于响应的功能。您必须自己做所有事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 2011-11-15
    • 2014-02-10
    • 2013-10-21
    • 2011-11-28
    • 2013-10-22
    • 1970-01-01
    相关资源
    最近更新 更多