栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

AngularJS:在哪里使用promise?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

AngularJS:在哪里使用promise?

这并不是您问题的完整答案,但是希望当您尝试阅读

$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.then(firstFn).then(secondFn);

then
方法将一条步骤添加到链中,然后返回代表扩展链最终结果的新promise。您可以根据需要添加任意多个步骤。

到目前为止,我们已经建立了功能链,但是实际上什么也没有发生。您可以通过调用开始

deferred.resolve
,指定要传递给链中第一步的初始值:

 deferred.resolve('initial value');

然后…仍然没有任何反应。为了确保正确观察模型更改,Angular直到下一次

$apply
调用时才真正调用链中的第一步:

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

那么错误处理呢?到目前为止,我们只在链的每个步骤中指定了一个 成功处理程序

then
还接受错误处理程序作为可选的第二个参数。这是承诺链的另一个更长的例子,这次是错误处理:

 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的交互封装在单独的服务中,并将结果按承诺传递给控制器​​。这样,您就可以使控制器与外部问题分开,并通过模拟服务更轻松地对其进行测试。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/484480.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号