博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AngularJS中$q的promise使用及链式调用传值问题
阅读量:6715 次
发布时间:2019-06-25

本文共 5032 字,大约阅读时间需要 16 分钟。

promise是什么

这里不解释promise是什么,因为我相信你来看文章的时候已经知道你什么是promise了。

此处有promise规范。

ES2016:

$q

  • $q是AngularJS提供的一个服务。

  • $q是跟AngularJS的$rootScope模板集成的,所以在AngularJS中执行和拒绝都很快。(编辑器疯了,dollar符号就是打不出来,就叫 'dollar'q)

  • $q是跟AngularJS模板引擎集成的,这意味着在视图中找到任何Promise都会在视图中被执行或者拒绝。

如何在AngularJS中使用

直接上栗子,程序员都不喜欢听你废话~〒▽〒

var app = angular.module('app', [])            .controller('testController', function ($scope, $q) {                //定义一个defer                var defer = $q.defer();                var promise = defer.promise;                promise.then(function (data) {                    //成功后的逻辑处理                }, function (error) {                    //失败后的逻辑处理                });                //模拟通过--实际应该是一个异步的callback中调用                defer.resolve('[data]');                //模拟拒绝--实际应该是一个异步的callback中调用                defer.reject('[data]');            });

链式调用

then会返回一个新的promise对象,所以直接jQuery风格的链式调用。

还是直接上栗子:

var app = angular.module('app', [])            .controller('testController', function ($scope, $q) {                //定义一个defer                var defer = $q.defer();                var promise = defer.promise;                promise.then(function () {                    console.log('then-resolved-1');                }, function () {                    console.log('then-rejected-1');                })                .then(function () {                    console.log('then-resolved-2');                }, function () {                    console.log('then-rejected-2');                });                //模拟通过--实际应该是一个异步的callback中调用                defer.resolve('[data]');                //模拟拒绝--实际应该是一个异步的callback中调用                defer.reject('[data]');            });

来看下是如何实现链式调用的,下面是AngularJS源码实现:

//angular.js  Promise.prototype = {    then: function(onFulfilled, onRejected, progressBack) {      var result = new Deferred();//此处可以看出,每个then都会返回一个新的Deferred对象。      this.$$state.pending = this.$$state.pending || [];      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);      return result.promise;    },    //其他省略    ...    }//Deferred定义  function Deferred() {    this.promise = new Promise();//可以看到defer的promise对象是一个new Promise()    //Necessary to support unbound execution :/    this.resolve = simpleBind(this, this.resolve);    this.reject = simpleBind(this, this.reject);    this.notify = simpleBind(this, this.notify);  }

链式调用参数传递

看过上面链式调用的栗子和AngularJS的源码后,大家就能知道每个then的上下文其实是不一样的,因为每次都是新new 出来的Promise对象。

先给栗子:

var app = angular.module('app', [])        .controller('testController', function ($scope, $q) {            //定义一个defer            var defer = $q.defer();            var promise = defer.promise;            promise.then(function (data) {                //...                return data;// data = 1            }, function (error) {                //...            })            .then(function (data) {                //...                return data;//data = 1            }, function (error) {                //...            });            //模拟通过--实际应该是一个异步的callback中调用            defer.resolve('1');        });

接下来看一段源码解析,看看AngularJS是如何调用Promise的。

//angular.js Deferred.prototype = {    resolve: function(val) {      if (this.promise.$$state.status) return;      if (val === this.promise) {        this.$$reject($qMinErr(          'qcycle',          "Expected promise to be resolved with value other than itself '{0}'",          val));      }      else {        this.$$resolve(val);//实际调用这个方法      }    },    $$resolve: function(val) {      var then, fns;      fns = callOnce(this, this.$$resolve, this.$$reject);      try {        if ((isObject(val) || isFunction(val))) then = val && val.then;        if (isFunction(then)) {          this.promise.$$state.status = -1;          then.call(val, fns[0], fns[1], this.notify);        } else {          this.promise.$$state.value = val;          this.promise.$$state.status = 1;          scheduleProcessQueue(this.promise.$$state);//最终在此处加入到队列中        }      } catch (e) {        fns[1](e);        exceptionHandler(e);      }    },...        //scheduleProcessQueue定义   function scheduleProcessQueue(state) {    if (state.processScheduled || !state.pending) return;    state.processScheduled = true;    nextTick(function() { processQueue(state); });//此处调用进入processQueue  } function processQueue(state) {    var fn, promise, pending;    pending = state.pending;    state.processScheduled = false;    state.pending = undefined;    for (var i = 0, ii = pending.length; i < ii; ++i) {      promise = pending[i][0];      fn = pending[i][state.status];      try {        if (isFunction(fn)) {          promise.resolve(fn(state.value));//此处是链式调用传参关键,fn(state.value)实际是上一个then的resolve的返回值,所以能知道,如果需要所有的then都能取到异步任务的返回值,就得在then的resolve函数中,将值返回。        } else if (state.status === 1) {          promise.resolve(state.value);        } else {          promise.reject(state.value);        }      } catch (e) {        promise.reject(e);        exceptionHandler(e);      }    }  }

转载地址:http://bhelo.baihongyu.com/

你可能感兴趣的文章
虚拟化中虚拟机处理器核数与物理主机cpu的关系
查看>>
org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type
查看>>
MYSQL: mysqlbinlog读取二进制文件报错read_log_event()
查看>>
随机产生由特殊字符,大小写字母以及数字组成的字符串,且每种字符都至少出现一次...
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
java21:捕鱼达人
查看>>
Zabbix 服务端搭建
查看>>
Java - 一个单例
查看>>
学习JAVA 持续更新
查看>>
Spring propertyConfigurer类
查看>>
Linux系统分析工具之uptime,top(一)
查看>>
EIGRP之DUAL(扩散更新算法)
查看>>
cacti自定义数据收集脚本,创建Data Templates和Graph Templates
查看>>
对你同样重要的非技术贴,一封有效的求职信的具体写法
查看>>
在路由器里插入和删除ACL
查看>>
我的友情链接
查看>>
OpenStack从入门到放弃
查看>>
戴尔和EMC已经成为正式的竞争对手
查看>>
6425C-Lab12 管理DC(1)
查看>>