gpt4 book ai didi

AngularJS : Where to use promises?

转载 作者:行者123 更新时间:2023-12-03 04:25:21 24 4
gpt4 key购买 nike

我看到了一些使用 的 Facebook 登录服务示例。 promise 访问 FB Graph API。

示例 #1 :

this.api = function(item) {
var deferred = $q.defer();
if (item) {
facebook.FB.api('/' + item, function (result) {
$rootScope.$apply(function () {
if (angular.isUndefined(result.error)) {
deferred.resolve(result);
} else {
deferred.reject(result.error);
}
});
});
}
return deferred.promise;
}

和使用的服务 "$scope.$digest() // Manual scope evaluation"什么时候收到回复

示例 #2 :
angular.module('HomePageModule', []).factory('facebookConnect', function() {
return new function() {
this.askFacebookForAuthentication = function(fail, success) {
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', success);
} else {
fail('User cancelled login or did not fully authorize.');
}
});
}
}
});

function ConnectCtrl(facebookConnect, $scope, $resource) {

$scope.user = {}
$scope.error = null;

$scope.registerWithFacebook = function() {
facebookConnect.askFacebookForAuthentication(
function(reason) { // fail
$scope.error = reason;
}, function(user) { // success
$scope.user = user
$scope.$digest() // Manual scope evaluation
});
}
}

JSFiddle

问题是:
  • 什么是差异在上面的例子中?
  • 什么是原因 案例 使用 $q 服务?
  • 以及它是怎么做的工作 ?
  • 最佳答案

    这不会是您问题的完整答案,但希望这会在您尝试阅读 $q 上的文档时对您和其他人有所帮助。服务。我花了一段时间才理解它。

    让我们暂时把 AngularJS 放在一边,只考虑 Facebook API 调用。当来自 Facebook 的响应可用时,这两个 API 调用都使用回调机制来通知调用者:

      facebook.FB.api('/' + item, function (result) {
    if (result.error) {
    // handle error
    } else {
    // handle success
    }
    });
    // program continues while request is pending
    ...

    这是在 JavaScript 和其他语言中处理异步操作的标准模式。

    当您需要执行一系列异步操作时,这种模式会出现一个大问题,其中每个连续操作都取决于前一个操作的结果。这就是这段代码的作用:
      FB.login(function(response) {
    if (response.authResponse) {
    FB.api('/me', success);
    } else {
    fail('User cancelled login or did not fully authorize.');
    }
    });

    首先它尝试登录,然后只有在验证登录成功后才向 Graph API 发出请求。

    即使在这种仅将两个操作链接在一起的情况下,事情也开始变得困惑。方法 askFacebookForAuthentication接受失败和成功的回调,但是当 FB.login 时会发生什么成功但 FB.api失败?此方法始终调用 success无论 FB.api 的结果如何,回调方法。

    现在想象一下,您正在尝试编写一个由三个或更多异步操作组成的健壮序列,其方式可以正确处理每个步骤的错误,并且在几周后对其他人甚至您都清晰易读。可能,但是很容易只是继续嵌套这些回调并在此过程中丢失对错误的跟踪。

    现在,让我们暂时将 Facebook API 放在一边,只考虑由 $q 实现的 Angular Promises API。服务。此服务实现的模式是尝试将异步编程转回类似于线性系列简单语句的东西,能够在任何一步“抛出”错误并在最后处理它,语义上类似于熟悉 try/catch块。

    考虑这个人为的例子。假设我们有两个函数,其中第二个函数使用第一个函数的结果:
     var firstFn = function(param) {
    // do something with param
    return 'firstResult';
    };

    var secondFn = function(param) {
    // do something with param
    return 'secondResult';
    };

    secondFn(firstFn());

    现在想象 firstFn 和 secondFn 都需要很长时间才能完成,所以我们想异步处理这个序列。首先我们新建一个 deferred对象,表示一系列操作:
     var deferred = $q.defer();
    var promise = deferred.promise;
    promise属性表示链的最终结果。如果您在创建后立即记录 promise ,您将看到它只是一个空对象( {} )。没什么可看的,继续前进。

    到目前为止,我们的 promise 仅代表链中的起点。现在让我们添加我们的两个操作:
     promise = promise.then(firstFn).then(secondFn);
    then方法向链中添加一个步骤,然后返回一个新的 promise ,表示扩展链的最终结果。您可以根据需要添加任意数量的步骤。

    到目前为止,我们已经建立了我们的功能链,但实际上什么也没发生。您可以调用 deferred.resolve 开始工作,指定要传递给链中第一个实际步骤的初始值:
     deferred.resolve('initial value');

    然后……仍然没有任何 react 。为了确保正确观察模型更改,Angular 直到下一次 $apply 才真正调用链中的第一步。被称为:
     deferred.resolve('initial value');
    $rootScope.$apply();

    // or
    $rootScope.$apply(function() {
    deferred.resolve('initial value');
    });

    那么错误处理呢?到目前为止,我们只在链中的每一步指定了一个成功处理程序。 then还接受错误处理程序作为可选的第二个参数。这是另一个更长的 promise 链示例,这次是错误处理:
     var firstFn = function(param) {
    // do something with param
    if (param == 'bad value') {
    return $q.reject('invalid value');
    } else {
    return 'firstResult';
    }
    };

    var secondFn = function(param) {
    // do something with param
    if (param == 'bad value') {
    return $q.reject('invalid value');
    } else {
    return 'secondResult';
    }
    };

    var thirdFn = function(param) {
    // do something with param
    return 'thirdResult';
    };

    var errorFn = function(message) {
    // handle error
    };

    var deferred = $q.defer();
    var promise = deferred.promise.then(firstFn).then(secondFn).then(thirdFn, errorFn);

    正如您在此示例中看到的,链中的每个处理程序都有机会将流量转移到下一个错误处理程序而不是下一个成功处理程序。在大多数情况下,您可以在链的末尾拥有一个错误处理程序,但您也可以拥有尝试恢复的中间错误处理程序。

    为了快速回到您的示例(和您的问题),我只想说它们代表了两种不同的方式,使 Facebook 的面向回调的 API 适应 Angular 观察模型变化的方式。第一个示例将 API 调用包装在一个 promise 中,它可以被添加到一个作用域中,并且可以被 Angular 的模板系统理解。第二种采用更暴力的方法,直接在作用域上设置回调结果,然后调用 $scope.$digest()让 Angular 知道来自外部来源的变化。

    这两个示例不能直接比较,因为第一个示例缺少登录步骤。然而,通常希望将与外部 API 的交互封装在单独的服务中,并将结果作为 promise 传递给 Controller ​​。通过这种方式,您可以将 Controller 与外部关注点分开,并使用模拟服务更轻松地测试它们。

    关于AngularJS : Where to use promises?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15604196/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com