【问题标题】:jQuery dependent AJAX call promisejQuery 依赖的 AJAX 调用承诺
【发布时间】:2018-07-30 18:30:39
【问题描述】:

我有 2 个异步调用

function async1() {
  return $j.post('/call1', JSON.stringify({
    id: my_id
  }), function(response) {
    if (response.success) {
      // resolve
    } else {
      // reject
    }
  });
}

function async2() {
  return $j.post('/call2', JSON.stringify({
    id: my_id
  }), function(response) {
    if (response.success) {
      // resolve
    } else {
      // reject
    }
  });
}

main() 函数我需要先调用async1(),如果成功,将调用async2()

我打算返回来自main() 的承诺。我主要担心的是我需要根据回复明确解决或拒绝。谁能告诉我如何使用 promises/deferred 来实现它?

【问题讨论】:

  • 您使用的是什么版本的 jQuery? v1、v2、v3?
  • @T.J.Crowder 我正在使用 v1
  • 你想返回一个原生的 Promise?还是 jQuery Deferred?
  • @T.J.Crowder jQuery 承诺

标签: javascript jquery promise


【解决方案1】:

我主要关心的是,我需要根据回复明确解决或拒绝。

好担心:不,你没有。只需使用 jQuery 的post 的承诺所给出的结果即可。

由于您使用的是 jQuery v1.x,我只需要注意它的 Deferred 对象符合 Promises/A+。你可能关心也可能不关心。不过,我假设您使用的是 v1.8 或更高版本。

因此,如果您可以使用 jQuery 的非 Promises/A+ 兼容的 Deferred 和 Promise,那么只需返回 post 的结果。

我会坚持使用 ES5 语法,因为您使用的是 jQuery v1.x,而且我猜您没有进行转译,等等。

function async1(my_id/* I assume it's a parameter?*/) {
    return $j.post(
        '/call1',
        JSON.stringify({id: my_id})
    );
}

function async2(my_id/* I assume it's a parameter?*/) {
    return $j.post(
        '/call2',
        JSON.stringify({id: my_id})
    );
}

...在main 中,使用那些“承诺”:

function main(some_id) {
    return async1(some_id).then(function(result1) {
        return async2(some_id).then(function(result2) {
            return [result1, result2];
        });
    });
}

该示例有 main 返回一个数组的承诺,其中数组中的第一个条目将是来自 async1 的结果,第二个是来自 async2 的结果(或者它拒绝因为其中一个失败的)。不过,您可以通过更改第二个 then 处理程序中的返回值来随意调整它。

如果您希望 main 改为返回本机承诺(必要时使用 polyfill),我可能会通过给自己提供 post 的包装器来尽早转换为本机承诺原生承诺:

function postPromise() {
    var args = Array.prototype.slice.call(arguments);
    return new Promise(function(resolve, reject) {
        $j.post.apply($j, args)
            .done(resolve)
            .fail(function(jqXHR, textStatus, errorThrown) {
                if (errorThrown) {
                    reject(errorThrown);
                } else {
                    reject(new Error(textStatus)); // or whatever
                }
            });
    });
}

然后

function async1(my_id/* I assume it's a parameter?*/) {
    return postPromise(
        '/call1',
        JSON.stringify({id: my_id})
    );
}

function async2(my_id/* I assume it's a parameter?*/) {
    return postPromise(
        '/call2',
        JSON.stringify({id: my_id})
    );
}

...在main 中,使用那些“承诺”:

function main() {
    return async1("the-id").then(function(result1) {
        return async2("the-id").then(function(result2) {
            return [result1, result2];
        });
    });
}

这具有使用 jQuery

【讨论】:

  • 基本上 'async1' 可以成功完成,根据作为响应获得的某些数据的值,我需要拒绝或解决。这怎么可能?
  • @Vivek:抱歉,恐怕这不是很清楚。即使async1 失败,您也想拨打async2 吗? 仅在失败时?只有当它成功的时候?
  • 只有在 async1 成功时才调用 async2。这里需要注意的是成功条件。如果我得到成功的回复说 responseData 并且如果 responseData.someVariable == false ,则不应调用 async2。
  • @Vivek:只需将条件放在来自async 的调用的then 处理程序中,然后返回其他内容或返回调用async2 的结果。
【解决方案2】:

您首先调用 async1(),然后在 async1() 成功响应时执行 async2() 函数。像这样:

function async1() {

  return $j.post(
        '/call1',
        JSON.stringify({id: my_id}),
        async2(response)    // <-- Replace function(response){} to this.
  });

}

然后在 async2 函数上:

function async2(dataAsync1) {
  var data = dataAsync1;  //Response from previews Ajax call...
                          //TODO: Handle this
  return $j.post(
    '/call2',
    JSON.stringify({id: my_id}),
    function(response) {
        if (response.success) {
            // resolve
        }
        else {
            // reject
        }
   });
}

【讨论】:

    【解决方案3】:

    可以这样:

    function async1() {
    
      return new Promise((resolve, reject) => $j.post(
          '/call1',
          JSON.stringify({
            id: my_id
          }),
          function(response) {
            if (response.success) {
              resolve( /*pass whatever*/ )
            } else {
              reject( /*pass whatever*/ )
            }
          });
      }
    }
    
    function async2() {
    
      return new Promise((resolve, reject) => $j.post(
          '/call2',
          JSON.stringify({
            id: my_id
          }),
          function(response) {
            if (response.success) {
              resolve( /*pass whatever*/ );
            } else {
              reject( /*pass whatever*/ )
            }
          });
      }
    }
    
    function main() {
      async1().then(async2).then((success) => console.log(success)).catch(err => console.error(err));
    }

    【讨论】:

    • 代码转储不是有用的答案,如果你打算在已经有一个 thenable 时使用new Promise,你需要解释为什么它比使用 thenable。
    • 1. deferreds 是(反模式)[stackoverflow.com/questions/30750207/…,jquery promise 的实现与标准背道而驰,正在消亡。 2.关于代码转储,我一般同意,但如果代码是自我解释的,我还是可以的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多