zoukankan      html  css  js  c++  java
  • $q -- AngularJS中的服务

    此 承诺/延迟(promise/deferred)实现 的灵感来自于 Kris Kowal's Q
    CommonJS Promise建议文档 将承诺(promise) 作为和 异步执行操作(action)结果对象进行交互的接口,在指定的时间内可能会也可能不会完成。
    从错误处理的角度看,延迟(deferred )和承诺(promise ) API 对于异步编程来说, 和同步编程的 try,catch, 以及 throw 作用差不多.

    // 为了演示的目的,此处我们假设 `$q`, `scope` 以及 `okToGreet` 引用 在当前执行环境中可用
    // (比如他们已经被注入,或者被当做参数传进来了).
      
    function asyncGreet(name) {
      var deferred = $q.defer();
      
      setTimeout(function() {
        // 因为此function 在未来的事件循环中异步执行,
        // 我们需要把代码包装到到一个 $apply 调用中,以便正确的观察到 model 的改变
        scope.$apply(function() {
          deferred.notify('即将问候 ' + name + '.');
      
          if (okToGreet(name)) {
            deferred.resolve('你好, ' + name + '!');
          } else {
            deferred.reject('拒绝问候 ' + name + ' .');
          }
        });
      }, 1000);
      
      return deferred.promise;
    }
      
    var promise = asyncGreet('小漠漠');
    promise.then(function(greeting) {
      alert('成功: ' + greeting);
    }, function(reason) {
      alert('失败鸟: ' + reason);
    }, function(update) {
      alert('收到通知: ' + update);
    });
    

      引人这种额外的复杂性的效果 在起初可能不明显。 在 promise 和 deferred APIs 进行承诺时好处就看出来了,请参考: https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md
    另外 promise api允许那些在传统的回调( CPS )方法中很难的实现的组合。 更多信息请查阅 Q文档,特别是 串行与并行的合并一节。

    延迟接口 | Deferred API

    通过调用 $q.defer() 可以构建一个新的 deffered 实例。
    deffered 对象用来将 Promise 实例与 标记任务状态(执行成功还是不成功)的 API 相关联。

    deffered 对象的方法

    resolve(value) ——传入 value 解决派生的 promise。 如果 value 是一个通过 $q.reject 构造的拒绝对象(rejection) , 该promise 将被拒绝。reject(reason) ——拒绝派生的promise,并提供原因 。 这相当于通过 $q.reject构造的拒绝对象(rejection)作为参数传递给 resolve。notify(value) ——在 promise 执行的过程中提供状态更新。 这在 promise 被解决或拒绝之前可能会被多次调用。

     

    deffered 对象的属性

    promise – {Promise} —— 与延迟(deferred)相关联的 promise 对象。

    承诺 接口 | Promise API

    当创建 deferred 实例时会创建一个新的 promise 对象,并可以通过 deferred.promise 得到该引用。
    promise 对象的目的是在 deferred 任务完成时,允许感兴趣的部分取得其执行结果。

    promise 对象的方法

    then(successCallback, errorCallback, notifyCallback) ——不管 promise 是被处理还是被拒绝, 一旦结果可用,then 就会尽快地异步调用 成功/错误 回调函数 只要结果是可用的。 调用回调函数时传递单个参数: 结果 或拒绝的理由。 此外,notify 回调可能被调用 0到多次,以提供 提供一个进度指示,之前承诺解决或拒绝。 这个方法 返回一个新的promise 对象, 根据 successCallback , errorCallback的返回值进行解决或拒绝 。 它还通过 notifyCallback 方法的返回值进行通知。 promise 不能从notifyCallback方法得到解决或拒绝 。
    catch(errorCallback) —— promise.then(null, errorCallback) 的快捷方式 finally(callback) ——让你可以观察到一个 promise 是被执行还是被拒绝, 但这样做不用修改最后的 value值。 这可以用来做一些释放资源或者清理无用对象的工作,不管promise 被拒绝还是解决。 更多的信息请参阅 完整文档规范. 因为在 ES3版本的JavaScript中 finally 是一个保留字关键字,不能作为属性名,为了适配 IE8,您需要使用 promise['finally'](callback) 这种形式来调用该方法。

    promise 链 | Chaining promises

    因为调用一个 promise 的 then 方法返回一个新的派生 promise实例,所以构建promises链也是很容易的:

    promiseB = promiseA.then(function(result) {
      return result + 1;
    });
      
    // promiseB 将会在处理完 promiseA 之后立刻被处理,
    // 并且其  value值是promiseA的结果增加1
    

      我们可以创建任意长度的promise链;因为一个promise可以被另一个promises处理(进一步推迟解决完成时间),所以在promise链上的任意一点进行 暂停/推迟解决 都是可行的。 这使得实现功能强大的APIs 成为现实,例如 $http 的响应拦截器。

    Kris Kowal's Q 与 $q 之间的区别

    主要区别有两点:
    Angular中的$q 集成了 ng.$rootScope.Scope Scope模型观察机制,这意味着对models 的解决或拒绝速度将会更快,避免不必要的浏览器重绘(会导致UI闪烁)。Q 比 $q拥有更多的功能特性,但带来的是代码字节数的增加。 $q 很轻量级,但包含了一般异步任务所需的所有重要功能。

    测试

    it('should simulate promise', inject(function($q, $rootScope) {
      var deferred = $q.defer();
      var promise = deferred.promise;
      var resolvedValue;
      
      promise.then(function(value) { resolvedValue = value; });
      expect(resolvedValue).toBeUndefined();
      
      // 模拟 promise 的 resolving
      deferred.resolve(123);
      // 注意 'then' function 不是同步调用的.
      // 因为我们想要  promise API 一直是异步的(async),
      // 不管是在同步调用还是异步调用中都是如此.
      expect(resolvedValue).toBeUndefined();
      
      // 使用 $apply()将 promise resolution 传递到 'then' functions .
      $rootScope.$apply();
      expect(resolvedValue).toEqual(123);
    }));
    

      

    依赖关系 | Dependencies

    $rootScope 

    方法 | Methods

    all(promises)

    结合多个promises为单个promise,在所有输入的promise都处理之后,组合之后的promise才会处理完成。
    参数: promises类型: Array./Object. 描述: promises的数组或者引用返回: Promise 返回单个的 promise,将与一个数组解决/散列值, 每个值对应于在相同的索引/关键的承诺 承诺 /散列数组。 如果任何承诺解决排斥,这产生的承诺将被拒绝 拒绝相同的值。

    defer()

    创建一个 递延 对象代表一个将来完成任务。
    返回 Deferred 返回一个新实例的Deferred。

    reject(reason)

    创建一个指定拒绝 原因 的promise 。 此api应该 用于在一个promises链中进行拒绝。 如果你正在处理promise 链中的最后一个promise ,你不需要担心。

    把 deferreds/promises 与我们熟悉的的 try/catch/throw行为进行对比,可以认为 reject 相当于JavaScript 中的throw 关键字。 这也意味着如果你通过一个 promise 的 error回调, “catch”了一个错误 ,你想错误的承诺 目前的承诺,你必须重新抛出“错误通过返回一个拒绝通过 拒绝 。

    promiseB = promiseA.then(function(result) {
      // success: 此处可以执行某些操作,然后直接使用原有的result,
      // 或者对result进行操作,来处理接下来的promiseB
      return result;
    }, function(reason) {
      // error: handle the error if possible and
      //        resolve promiseB with newPromiseOrValue,
      //        否则转向拒绝 promiseB 的分支
      if (canHandle(reason)) {
       // 处理错误和恢复
       return newPromiseOrValue;
      }
      return $q.reject(reason);
    });
    

      参数: reason类型: *描述: Constant, message, exception 或代表拒绝原因的 object。返回: Promise 返回一个promise ,已经因为 reason 而被拒绝了 。

    when(value)

    将一个对象(可能是value 或 [第三方]then-able promise) 包装为一个 $q promise。 这在你不确定所处理的对象可能是也可能不是一个promise 时是很有用的,有可能该对象来自于一个不被信任的源头。
    参数: value类型: *描述: promise 的值返回 Promise 根据传入的值/或promise 返回一个包装后的 promise

  • 相关阅读:
    C# 实现 Snowflake算法生成唯一性Id
    kafka可视化客户端工具(Kafka Tool)的基本使用(转)
    docker 安装kafka
    Model类代码生成器
    使用docker 部署rabbitmq 镜像
    Vue 增删改查 demo
    git 提交代码到库
    Android ble蓝牙问题
    mac 配置 ssh 到git (Could not resolve hostname github.com, Failed to connect to github.com port 443 Operation timed out)
    okhttp
  • 原文地址:https://www.cnblogs.com/alphafly/p/4689480.html
Copyright © 2011-2022 走看看