【问题标题】:Synchronous function calls involving post json calls where one function should succeed upon the success of another function涉及 post json 调用的同步函数调用,其中一个函数应该在另一个函数成功时成功
【发布时间】:2012-07-12 04:11:00
【问题描述】:

我有两个功能,其中之一包括多个 json 调用,它们是自然发布的。

我希望这些是同步的。也就是说,一个应该只在上一篇文章完成后运行(如果所有帖子都完成并成功,我希望第二个函数触发)。

代码结构有点像这样:

    $.getSomeData = function() {
    $.postJSON("iwantdata.htm",{data:data},function(data)){
    });

    $.postJSON("iwantmoredata.htm",{data:data},function(data)){
    });
    });

    $.useSomeData = function() {
});

useSomeData 必须适用于后续的 json 调用。

谁能帮帮我?提前致谢。

【问题讨论】:

  • 我建议编辑您的答案和标题以删除出现的“同步”一词。这不是 JSON 中“同步”的含义(如果 XML HTTP 请求等待服务器继续处理客户端代码,则它是同步的,通常是一件坏事)。您是否在寻找“原子”这个词,这意味着它们要么都成功要么都失败?或者您是否只想将这些链接起来,这样一旦您获得第一个输出,您就要求更多输出......但需要注意的是,如果有一个失败,则链停止处理?

标签: javascript jquery json post


【解决方案1】:

所以基本上你想要这样的东西:

function chainPost(url1, url2, initialInput, func) {
    $.post(url1, {data: initialInput})
        .done(function (initialOutput) {
            $.post(url2, {data: initialOutput})
                .done(function (secondOutput) {
                    func(initialOutput, secondOutput);
                });
        });
}

chainPost("iwantdata.htm", "iwantmoredata.htm", 0, function (first, second) {
    alert(first);
    alert(second);
});

【讨论】:

    【解决方案2】:

    你可以只嵌套它们,在第一个的完成函数中开始第二个,依此类推:

    $.getSomeData = function() {
       $.postJSON("iwantdata.htm",{data:data},function(data) {
           $.postJSON("iwantmoredata.htm",{data:data},function(data)){
               // use the data here
           });
       });
    };
    

    在处理异步函数时,不能写如下代码:

    $.getSomeData();
    $.useSomeData();
    

    根据定义,第一个是异步的,因此在调用第二个函数时它还没有完成,并且在异步操作完成之前,javascript 无法停止 JS 执行。

    您可以将您的 use 函数传递给 get 函数,然后在数据可用时调用它,作为上述示例的补充,如下所示:

    $.getSomeData = function(fn) {
       $.postJSON("iwantdata.htm",{data:data},function(data) {
           $.postJSON("iwantmoredata.htm",{data:data},function(data)){
               fn(data);
           });
       });
    };
    

    然后,您将拥有一个 getSomeData(useFn) 函数,该函数将在所有数据准备就绪时调用该函数的参数。

    【讨论】:

      【解决方案3】:

      Deferred objects [docs] 非常适合这个。不幸的是,您的代码示例包含语法错误,并且不清楚调用是如何嵌套的。所以,我不确定您是要一个接一个地运行两个 Ajax 调用还是并行运行,但任何一种方式都是可能的。

      这里有两个例子。查看文档以获取更多信息并尝试使用它。

      注意: .postJSON 不是内置的 jQuery 方法,我在这里假设您从 $.ajax(或 $.post)函数返回返回值。

      并行 Ajax 调用:

      $.getSomeData = function() {
          var a = $.postJSON("iwantdata.htm", {data:data});
          var b = $.postJSON("iwantmoredata.htm", {data:data});
      
          // return a new promise object which gets resolved when both calls are
          // successful
          return $.when(a, b);
      };
      
      // when both calls are successful, call `$.useSomeData`
      // it will have access to the responses of both Ajax calls
      $.getSomeData.done($.useSomeData);
      

      见:$.when

      链式 Ajax 调用:

      ... 第一个调用的响应是第二个调用的输入。这只是一个例子,当然你可以传递任何你想要的数据。

      $.getSomeData = function() {
          return $.postJSON("iwantdata.htm", {data:data}).pipe(function(response) {
              // execute the second Ajax call upon successful completion 
              // of the first one
              return $.postJSON("iwantmoredata.htm", {data:response});
          });
      };
      
      // if both Ajax calls are successful, call `$.useSomeData`
      // it will have access to the response of the second Ajax call
      $.getSomeData.done($.useSomeData);
      

      见:deferred.pipe()

      如果您有更复杂的逻辑,您还可以创建、解析或拒绝您自己的延迟对象。查看文档中的示例。

      【讨论】:

      • 请注意,您的链接示例使用第一次调用的结果作为第二次调用的参数
      • @Bergi:是的,这似乎是最有意义的......这只是一个例子。
      • 没错——链接它们的唯一原因是#2 需要来自#1 的数据:-)
      • @Bergi - 使用返回的数据不是链接的唯一原因。 #2 可能只是序列中的第二个操作,需要等待 #1 是否成功,但不需要 #1 的结果。还可能存在必须对操作进行排序的后端原因。
      猜你喜欢
      • 1970-01-01
      • 2019-11-09
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 2013-09-25
      • 1970-01-01
      • 2018-05-17
      相关资源
      最近更新 更多