【问题标题】:How to use jQuery's $.post() method with async/await and typescript如何在 async/await 和 typescript 中使用 jQuery 的 $.post() 方法
【发布时间】:2017-12-30 09:47:41
【问题描述】:

我在异步函数中的 await 语句是对 jQuery 的 $.post() 方法的调用,它返回一个有效的承诺,但是我在 TypeScript 中遇到了这个错误:

“await”操作数的类型必须是有效的承诺,或者不能包含可调用的“then”成员。

我的功能是这个(为示例简化)。代码有效且有效,但在 TS 控制台中出现错误。

 async function doAsyncPost() {
    const postUrl = 'some/url/';
    const postData = {name: 'foo', value: 'bar'};
    let postResult;
    let upateResult;

    function failed(message: string, body?: string) {
      console.log('error: ', message, ' body: ', body);
    }

    function promiseFunc() {
      return new Promise<void>( resolve => {
        // ... do something else....
        resolve();
      });
    };

    function finish() {
      // ... do something at the end...
    }

    try {
      // The error is on the $.post()
      postResult = await $.post(postUrl, $.param(postData));
      if (postResult.success !== 'true') {
        return failed('Error as occoured', 'Description.....');
      }      
      await promiseFunc();

      return finish();
    } catch (e) {
      await failed('Error as occoured', 'Description.....');
    }
  }

我猜 TS 的 $.post() 有问题,因为你可以在上面调用 .then(),但是我该如何解决这个问题呢?另外,我在更新 2.4.2 之前没有这个错误。

【问题讨论】:

  • 似乎 typescript 确实对 jQuery 返回一个 promise 对象感到讨厌,该对象也是一个 jqXHR 对象。尝试postResult = await Promise.resolve($.post(postUrl, $.param(postData))); 或者:postResult = await $.post(postUrl, $.param(postData)).then(); 尽管后者可能会触发相同的错误。
  • @trincot 您的两个解决方案都有效。似乎有点肮脏和不必要,但我猜是迄今为止最好的选择。如果您想提供您的评论作为答案,我会将其标记为已接受。

标签: jquery typescript es6-promise


【解决方案1】:

JQueryXHR 有自己的 .then() 版本,它有一些额外的选项:

then<R>(doneCallback: (data: any, textStatus: string, jqXHR: JQueryXHR) => R, failCallback?: (jqXHR: JQueryXHR, textStatus: string, errorThrown: any) => void): JQueryPromise<R>;

要在带有 $.post 的 TypeScript 中使用 await,我必须从 jquery.d.ts 中删除该行。然后 TypeScript 将看到在 JQueryGenericPromise 上定义的 .then。

【讨论】:

    【解决方案2】:

    似乎 TypeScript 确实讨厌 jQuery 返回一个既是 a deferred and a jqXHR object 的 promise 对象:

    从 jQuery 1.5 开始,$.ajax() 返回的 jqXHR 对象实现了 Promise 接口,为它们提供了 Promise 的所有属性、方法和行为(请参阅Deferred object 了解更多信息)。

    TypeScript 的这种顽固性至少有三种解决方法

    返回纯 ES6 Promise 的解决方案

    您可以将返回值传递给Promise.resolve(),这将返回一个真正的 ES6 Promise,承诺相同的值:

    postResult = await Promise.resolve($.post(postUrl, $.param(postData)));
    

    返回 jQuery 承诺的解决方案

    另外两个替代方案不返回纯 ES6 承诺,而是 jQuery 承诺,这仍然足够好。请注意,这些 Promise 对象仅符合 Promises/A+ from jQuery 3 及更高版本:

    您可以应用 deferred.promise method,它返回一个 jQuery 承诺对象:

    postResult = await $.post(postUrl, $.param(postData)).promise();
    

    或者,您可以应用 deferred.then method,它也返回一个 jQuery 承诺:

    从 jQuery 1.8 开始,deferred.then() 方法返回一个新的承诺

    通过不向then 提供任何参数,您实际上返回了具有相同承诺值的承诺:

    postResult = await $.post(postUrl, $.param(postData)).then();
    

    【讨论】:

    • 两个不错的解决方案!这也意味着您不必编辑 .d.ts 文件。
    • $.get(...).then() 对我不起作用,但 $.get(...).promise() 工作正常,并且更具可读性。
    • 感谢@kitsu.eb 提及,我已将promise 方法解决方案添加到我的答案中。 then 在 jQuery 1.8 之前将无法使用,这或许可以解释为什么它不适合您。
    猜你喜欢
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2019-01-17
    • 2018-10-07
    • 2018-01-16
    • 2018-06-29
    • 2019-03-15
    相关资源
    最近更新 更多