【问题标题】:How can I return a success and an error promise with and without data?如何在有数据和没有数据的情况下返回成功和错误承诺?
【发布时间】:2015-12-21 13:04:56
【问题描述】:

我想在 $http 调用之前或之后返回一个 Promise 和一个名为 output 的对象。有人可以告诉我如何使用 AngularJS 框架做到这一点,并且对于 Typescript 非常重要,这样我可以确定它工作正常吗?

 topicNewSubmit = (): ng.IPromise<any> => {
    var self = this;
    var myData1 = { abc: 123 }

    if (self.abc = 22) {
        // How can I return an OKAY promise from here?
    }
    if (self.abc = 33) {
        // How can I return an OKAY promise with myData1 from here?
    }
    if (self.abc = 88) {
        // How can I return a FAIL promise from here?
    }

    return self.$http({ url: self.url, method: "GET" })
        .then(
            (response: ng.IHttpPromiseCallbackArg<any>): any => {            
            var myData2 = { abc: 245 }
            // How can I return a promise and myData2. 
            // return(myData2) gives an error with Typescript

            // How can I return a promise and no data
            // return gives an error with Typescript 
        },
        (error: ng.IHttpPromiseCallbackArg<any>): ng.IPromise<any> => {
            var myData3 = { abc: 345 }
            // Is this the correct way to return an unhandled reject with myData3
            return self.$q.reject(myData);
        });
  }

【问题讨论】:

  • docs.angularjs.org/api/ng/service/$q#resolve $q 有一个 resolve 方法。如果您使用的是早期版本的 Angular,请使用 .when。他们做同样的事情。此外,$http 方法已经返回承诺。您不需要在内部使用另一个 Promise 链。
  • @ExplosionPills - 如果您有几分钟的时间,请根据我的简短代码示例添加您的 cmets 作为答案。我不太确定“$http 方法已经返回承诺。您不需要在内部使用另一个承诺链”是什么意思。我从测试中看到的一件事以及我添加 self.$q.reject 的原因是,如果我确实在没有返回的情况下处理了拒绝,那么我的 topicNewSubmit 将始终返回正常。希望这是有道理的。非常感谢。
  • 我建议你让它与普通的 javascript 一起工作,然后将它移植到 typescript,并不是说将它移植到 typescript 特别难......如果你知道 typescript 那么它应该很容易。

标签: javascript angularjs typescript


【解决方案1】:

编辑:修正了代码并添加了TypeScript Playground example。方法输入正确,您可以通过抛出的输入错误来验证这一点,尝试修复它们;)。我从角度定义文件中复制了非常基本的必需接口。

编辑 #2:Here's the fixed version 以上 TypeScript Playground 示例。

如果我正确理解了您的问题,您正在尝试为服务方法定义一个返回类型,说明它返回一个承诺,其解决后的结果将是某个对象?

在这种情况下,您就快到了,我已将您的两个示例方法分成不同的块,因为它们需要不同的方法。

总的来说,当您使用胖箭头方法时,我删除了范围复制 (self = this),这会自动将方法范围限定为外部词法范围。简而言之,没有必要进行范围复制,事实上,在您的示例中 self 并不总是指向服务(因为您复制的是方法内部而不是外部的范围)。

另外,请注意 Angular 承诺的定义(截断):

interface IDeferred<T> {
    resolve(value?: T): void;
    reject(reason?: any): void;
}

因此,键入 Angular Promise 只会为 promise 的 resolve 情况添加类型,而不是为被拒绝的情况。因此,在调用您的服务时,它会验证成功处理程序中的结果是您定义的类型,但错误处理程序中的参数类型是any。

主题测试

要使此方法起作用,您需要将$q 注入您的服务,然后使用它来创建您自己的deferred

topicTest = (): IPromise<Foo> => { // return a promise which will result in a parameter of MyType upon resolving
    var deferred = this.$q.defer<Foo>(); // Type the deferred to get better 'intellisense' support
    if (this.abc = 99) {
        deferred.resolve(new Foo());
    }
    if (this.abc = 88) {
        deferred.reject("You can pass in whatever you like to the reject case");
    }
    return deferred.promise;
};

主题新提交

$http 已经返回了 Promise,因此您只需附加一个 then 回调并从该方法中返回,以允许将其他 then 回调链接到它。

在这种情况下,您的服务方法的返回类型将是 angular.IPromise&lt;() =&gt; any&gt;,您可以将 any 替换为您想要的类型。 then 方法的返回类型必须与您在服务方法的返回类型中为通用占位符选择的任何类型相对应。

topicNewSubmit = () : IPromise<Foo> => {
    return this.$http({ url: this.url, method: "GET" }).then((response): Foo => {
        return new Foo();
    }, (error) => {
        return "whatever you'd like, it does not have to correspond to Foo";
    });
}

然后你可以像使用你的服务

MyService.topicNewSubmit().then((data) => {
    // data needs to be of type T, where T is the type you defined in the generic placeholder of IPromise<T>
}, (error: any) => {
    // In the error case, the parameters are of type any
});

【讨论】:

  • 感谢您的回答。在我的 IDE 中,topicNewSubmit 的返回输出显示为错误:Type '{ abc: string; }' 不可分配给类型 'IPromise'。同样在您的回答中,由于您正在处理 topicNewSubmit 中的错误,因此无法到达注释“// 同样错误现在等于 {abc: 'just an example'}”,因此它会返回成功。
  • 我不确定返回类型,稍后会验证。但是错误未在成功回调中处理,因此该示例将起作用。 then 方法接受两个回调一个成功和一个错误。
  • 嗨 Anne,我的错,我忘了更新错误回调的返回类型,在我的编辑中修复了这个问题。
  • 嗨,刚刚检查过,如果来自 $http 的错误得到处理,那么它不会转到“随便你”行。当我打开 Playground 时,它在我的浏览器上显示了很多语法错误。
  • @Anne 我知道,那是为了向您展示打字工作正常:)。如果错误得到处理,你的意思是什么?
【解决方案2】:

说实话,我觉得你的代码示例是在黑暗中拍摄,但这是我的解决方案。

和 Anzeo 一样,我删除了对 self 或 this 的引用。 $q 和 $http 应该分配到某个地方。

declare var $q: ng.IQService;
declare var $http: ng.IHttpService;

var topicNewSubmit = (): ng.IPromise<any> => {

    var deferred = $q.defer<any>();

    var myData1 = { abc: 123 };

    if (this.abc = 22) {

        deferred.resolve();

    } else if (this.abc = 33) {

        deferred.resolve(myData1);

    } else if (this.abc = 88) {

        deferred.reject();

    } else {

        $http({
            url: this.url,
            method: "GET"
        })
        .then(() => {
            deferred.resolve({ abc: 245 });
        }, () => {
            deferred.reject({ abc: 345 });
        });
    }

    return deferred.promise;
};

【讨论】:

    【解决方案3】:

    回答

    您不能返回尚不存在的东西,除非您阻止所有操作直到获得它。由于浏览器 JavaScript(大部分)是单线程的,您不想在文件下载时阻塞线程。因此,您返回一个最终会解决的 promise。消费者需要使用then 函数来最终获得价值。

    幽默

    承诺是终生的。它的?一直向下?

    【讨论】:

    • 我的问题是当我使用时: return self.$q.resolve(output);它告诉我这是无效的并且 $q.没有决心。
    • $q. does not have a resolve. 听起来像 old 版本的 angular
    • 那么如何从 $http 调用成功中返回数据呢?同样是 return self.$q.reject('Error during Multi-save');从 $http 调用的失败块中返回失败承诺的正确方法是什么?
    【解决方案4】:

    你可以像这样使用promise

    var deferred = $q.deferred();
      $http(api url and method)
        .success function() {
             deferred.resolve(); 
        }
        .failure function()  {
            deferred.reject(); 
        }
        return deferred.promise;
    

    【讨论】:

    猜你喜欢
    • 2021-08-10
    • 2020-07-08
    • 2014-08-03
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2015-06-21
    相关资源
    最近更新 更多