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;