1

当我尝试使用 Angular 从工厂函数返回 $http.post() 对象时,它会抛出这个错误:

在此处输入图像描述

下面是我的代码:

AngularUtils.js

Fenrir.factory('AngularUtils', function ($http, $log, $window) {

var AngularUtils = {
    save: function(url, obj, errors, not_show_error_toast) {            
        not_show_error_toast = typeof not_show_error_toast !== 'undefined' ? not_show_error_toast : false;
        loaderShow();
        if (angular.isDefined(obj.id)) {
            return $http.put(url + obj.id + '/', obj).
                then(function onSuccess(response) {
                    loaderHide();
                    angular.extend(obj, response);
                    errors = {};
                }), function onError(response) {
                    loaderHide();
                    handleErrors(response, status, errors, not_show_error_toast);
                };
        } else {
            return this.create(url, obj, errors, not_show_error_toast);
        }
    },
    create: function(url, obj, errors, not_show_error_toast) {            
        not_show_error_toast = typeof not_show_error_toast !== 'undefined' ? not_show_error_toast : false;
        return $http.post(url, obj).
            then(function onSuccess(response) {
                loaderHide();
                angular.extend(obj, response);
                errors = {};
            }), function onError(response) {
                loaderHide();
                handleErrors(response, status, errors, not_show_error_toast);
            };
    },
}

   return AngularUtils
})

管理员.js

var Fenrir = angular.module('Fenrir', []);

Fenrir.controller('AdminController', function ($scope, $http, AngularUtils) {
    $scope.createScreen = function () {
        AngularUtils.save('/admin/saveScreen', $scope.record, '', '').then(function (hubs) {
            $scope.hubs = hubs;
            console.log('In ctrl ' + $scope.hubs);
        });
    }
})

如何正确返回 $http.post() 对象?

4

1 回答 1

1

仔细查看错误消息:

TypeError: AngularUtils.save(...).then is not a function

这就是说没有then()AngularUtils.save(...). 这表明该save()函数确实执行了,但它没有按预期返回承诺。

所以你的工厂方法确实执行了,但是因为你没有返回一个承诺,我们只能推测执行最终导致了哪些路径。

更新:原始脚本中的语法错误

在尝试为您证明我的解决方案时,我发现您的$put().then()响应处理程序存在语法问题,括号位置错误,该onError函数应该是该函数的第二个参数then,而不是它之后。您的代码应如下所示:

return $http.put(url + obj.id + '/', obj).
            then(function onSuccess(response) {
                loaderHide();
                angular.extend(obj, response);
                errors = {};
            }, function onError(response) {
                loaderHide();
                handleErrors(response, status, errors, not_show_error_toast);
            });

微妙但重要的是,如果您没有严格编译,那么工厂函数根本没有正确编译,这可能会导致您的错误。


一个一些路径将返回异步承诺延迟(期货)的工厂方法中,默认模式虽然很冗长,但返回一个包裹整个方法执行的延迟,然后对于每个响应路径,您可以选择解决或通过从函数返回的原始承诺拒绝响应。

有不同的库和技术可以做到这一点,请参阅Rick Strahl的AngularJs 和 Promises with the $http Service了解常见实现的演练。

save: function(url, obj, errors, not_show_error_toast) {            
    var defer = $.Deferred();

    not_show_error_toast = typeof not_show_error_toast !== 'undefined' ? not_show_error_toast : false;

    if (angular.isDefined(obj.id)) {
        loaderShow(); // NOTE: let create manage the loader start if it needs to
        $http.put(url + obj.id + '/', obj).
            then(function onSuccess(response) {
                loaderHide();
                // HACK: because .then is used instead of .success, you probably want the response.data, please review this
                angular.extend(obj, response.data);

                defer.resolve(obj);
            }, function onError(response) {
                loaderHide();
                handleErrors(response, status, errors, not_show_error_toast);

                defer.reject(response);
            });
    } else {
        // If create is a deferral, it should be safe to return it directly
        return this.create(url, obj, errors, not_show_error_toast);
    }

    return defer.promise();
},

注意:仅在调用倒数end / hide / stop / close的同一范围内调用startshow实用程序或状态操作。如果您不遵循此规则,代码可以工作,但随着项目的发展,它会变得更难维护,因此我将调用移至我们知道将始终调用的分支中。这个函数范围不能假设函数最终会调用我们。loaderShow();loaderHide()create()loaderHide()

这是我们都需要摆脱的常见但坏习惯;)

于 2021-10-01T07:25:05.287 回答