返回一个空的承诺

Posted

技术标签:

【中文标题】返回一个空的承诺【英文标题】:Return an empty promise 【发布时间】:2015-07-12 07:49:33 【问题描述】:

我有一个返回 jQuery 承诺的函数。它看起来像这样:

addBooks(books: Array<Books>) 
    return $.ajax(
        url: '/Books/AddBooks/',
        type: 'POST',
        data: ko.toJSON(books),
        contentType: 'application/json'
    );

我这样做是为了重用这个函数和链式 promise 回调,例如:

addBooks.done(() =>  alert("Books added!"); )

我的问题是,如果我想尽早脱离 addBooks 并防止访问服务器怎么办。例如:

addBooks(books: Array<Books>) 

    // An empty array was passed in for some reason.
    // Theres nothing to add so dont try to POST
    if (books <= 0) return null;

    return $.ajax(
        url: '/Books/AddBooks/',
        type: 'POST',
        data: ko.toJSON(books),
        contentType: 'application/json'
    );

我的示例无法编译,因为我的链式完成回调示例期望 addBooks 返回一个承诺对象,而不是 null。我怎样才能(或者在这种情况下我应该返回什么正确的对象)?

【问题讨论】:

【参考方案1】:

你可以返回一个 resolved 承诺:而不是

if (books <= 0) return null;

使用

if (books <= 0) return $.Deferred().resolve();

小心,不过,jQuery 的 Promise API 做了一些令人惊讶的事情:有时它会调用你的 done/then/etc。与done/then/等同步回调。打电话,有时不会。大多数承诺库确保调用始终是异步的,即使您正在调用done/then/等。在一个已解决的承诺上。 jQuery 没有,所以你会得到细微的差别。

例如,这段代码:

addBooks(() => console.log(1));
console.log(2);

...将记录

2 1

...如果您进行了 ajax 调用,但是

1 2

...如果你返回了一个已解决的承诺。

【讨论】:

这可以编译,但我必须添加额外的代码,因为$.Deferred 的返回类型与$.ajax 的返回类型不同。我喜欢@Bergi 给出的答案,因为它的代码少了一点。【参考方案2】:

我怎样才能返回一个空的承诺(或者在这种情况下我应该返回什么正确的对象)?

是的,“空承诺”在这里是合适的,如果你的意思是一个已经兑现但一无所有的承诺(undefinednull)。

创建这样的 jQuery 语法是使用带有单个(或没有)参数的 $.when

if (books <= 0) return $.when(null);

【讨论】:

我不知道$.when 的这种用法,但它就在文档中! return $.Deferred().resolve(); 是更正确的答案。 @wonsuc 你为什么这么认为,你如何定义“正确”?【参考方案3】:

来自https://api.jquery.com/jquery.when/

如果您根本不传递任何参数,jQuery.when() 将返回一个已解决的承诺。

例如

if (books <= 0) return $.when();

并且,如果您需要一个未定义传递的值:

如果 单个参数 被传递给 jQuery.when() 并且它不是 Deferred 或 Promise,它将被视为已解决的 Deferred 和任何 doneCallbacks附加将立即执行。 doneCallbacks 被传递给原始参数。

例如传递一个空数组:

if (books <= 0) return $.when([]);

例如传递一个空对象:

if (books <= 0) return $.when();

【讨论】:

以上是关于返回一个空的承诺的主要内容,如果未能解决你的问题,请参考以下文章

像在 Q 中定义空的 Bluebird 承诺

返回使用另一个 PromiseKit 承诺的承诺

TypeScript:如何正确键入一个接受承诺并按原样返回该承诺的函数

如果一个已经在运行的 PromiseKit 承诺返回一个未决的承诺的最佳 Swift 模式是啥?

带着承诺走一棵树

承诺回调返回承诺