Transaction源码

Transaction模块用于实现,某构造函数的实例调用perform(method,args)方法时,在method函数执行前后调用特定钩子函数的功能。成对的前置钩子initialize函数和后置钩子close函数以数组形式添加,且前置钩子initialize函数用于向后置钩子close函数提供参数,在method函数前调用;后置钩子close在method函数后调用。

构造函数需原型继承Transaction,或原型方法逐个赋值。且getTransactionWrappers方法用于添加前置钩子与后置钩子;reinitializeTransaction方法在初始化时调用,用于清空前、后置钩子;perform方法实际执行method函数、及前后钩子。

'use strict';

var _prodInvariant = require('./reactProdInvariant');// 生产环境React形式带url报错

// invariant(condition,format,a,b,c,d,e,f) condition为否值,替换format中的"%s",并throw error报错
var invariant = require('fbjs/lib/invariant');

var OBSERVED_ERROR = {};

// 用于在某函数method执行前后,添加前置钩子initialize和后置钩子close,前置钩子的意义是向后置钩子提供参数
// 通过原型继承或原型方法赋值,将reinitializeTransaction、getTransactionWrappers、perform方法赋值给某构造函数的实例
// reinitializeTransaction方法在该实例初始化时执行
// getTransactionWrappers方法用于添加前、后置钩子,返回值为[{initialize:function(){},close:function(){}}]形式
// perform(method,args)方法触发前置钩子initialize、method(args)、后置钩子close的顺序执行
var TransactionImpl = {
  // 初始化
  reinitializeTransaction: function () {
    // 将前置钩子和后置钩子transactionWrapper添加到this.transactionWrappers中
    this.transactionWrappers = this.getTransactionWrappers();

    // 初始化后置钩子close方法的参数,由前置钩子initialize方法返回值构成
    if (this.wrapperInitData) {
      this.wrapperInitData.length = 0;
    } else {
      this.wrapperInitData = [];
    }

    this._isInTransaction = false;
  },

  _isInTransaction: false,

  // 用于添加method方法的前置钩子及后置钩子transactionWrapper={initialize:function(){},close:function(){}}
  // 前置钩子initialize方法为后置钩子close方法提供参数,且存放于this.wrapperInitData中
  // 返回值形如[{initialize:function(){},close:function(){}}]
  getTransactionWrappers: null,

  // 判断perform方法执行与否,由此断点closeAll方法是外部调用还是内部调用(不允许外部调用)
  isInTransaction: function () {
    return !!this._isInTransaction;
  },

  // 外部接口,执行各前置钩子initialize方法,随后执行method函数,最后执行后置钩子close方法
  perform: function (method, scope, a, b, c, d, e, f) {
    // 实例的perform方法单次只能执行一个
    !!this.isInTransaction() ? 
      process.env.NODE_ENV !== 'production' ? 
        invariant(false, 'Transaction.perform(...): ' 
          + 'Cannot initialize a transaction when there is already an outstanding transaction.') 
        : _prodInvariant('27') : void 0;

    var errorThrown;
    var ret;
    try {
      this._isInTransaction = true;// perform方法执行中标志
      errorThrown = true;
      this.initializeAll(0);
      ret = method.call(scope, a, b, c, d, e, f);
      errorThrown = false;
    } finally {
      try {
        if (errorThrown) {
          // method函数报错,捕获后置钩子的报错
          try {
            this.closeAll(0);
          } catch (err) {}
        } else {
          // method函数不报错,后置钩子正常报错
          this.closeAll(0);
        }
      } finally {
        this._isInTransaction = false;
      }
    }
    return ret;
  },

  // 内部调用,在method函数执行前,调用前置钩子transactionWrapper中的initialize方法
  initializeAll: function (startIndex) {
    var transactionWrappers = this.transactionWrappers;
    for (var i = startIndex; i < transactionWrappers.length; i++) {
      var wrapper = transactionWrappers[i];
      try {
        this.wrapperInitData[i] = OBSERVED_ERROR;
        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;
      } finally {
        // 报错即行跳过
        if (this.wrapperInitData[i] === OBSERVED_ERROR) {
          try {
            this.initializeAll(i + 1);
          } catch (err) {}
        }
      }
    }
  },

  // 内部调用,在method函数执行后,调用后置钩子transactionWrapper中的initialize方法
  closeAll: function (startIndex) {
    // 外部直接调用时报错,须由perform方法调用执行
    !this.isInTransaction() ? 
      process.env.NODE_ENV !== 'production' ? 
        invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') 
        : _prodInvariant('28') : void 0;

    var transactionWrappers = this.transactionWrappers;
    for (var i = startIndex; i < transactionWrappers.length; i++) {
      var wrapper = transactionWrappers[i];
      var initData = this.wrapperInitData[i];// 前置钩子返回值
      var errorThrown;
      try {
        errorThrown = true;
        if (initData !== OBSERVED_ERROR && wrapper.close) {
          wrapper.close.call(this, initData);
        }
        errorThrown = false;
      } finally {
        // 报错即行跳过
        if (errorThrown) {
          try {
            this.closeAll(i + 1);
          } catch (e) {}
        }
      }
    }

    // 清空提供给后置钩子close方法的参数
    this.wrapperInitData.length = 0;
  }
};

module.exports = TransactionImpl;

猜你喜欢

转载自schifred.iteye.com/blog/2354924