取引メカニズムは、このメカニズムの聞いたことがあるはずです反応し反応する開発者の一定の理解を持っているほぼすべての全体で最も一般的に使用される機能に反応する方法がSETSTATEを含め、提供反応
だから、取引メカニズムは最終的に反応する原則事項の実現のメカニズムを説明するために、そのような絵を描くように注釈付きソースコードと反応し、それのためのメカニズムのどのような種類であり、
この図によると、私たちはトランザクションを理解することができ、によってトランザクションがメソッドを包ん(それはコンドームと呼ばれる)の実行方法はwarpperを使用することで反応し、それぞれのinitializeメソッドwapper提供され、それが要求されるcloseメソッド、使用トランザクション提供される方法を使用してトランザクションを実行する、例えば、anyMethod上記画像のメソッドを呼び出し、メソッドは、渡された実行する必要があり、このときはまだ注文wrapper.initalize、anyMethod、wrapper.closeが、トランザクション内で実行されます包まwapper複数のトランザクションがanyMethodを行う順次前に全てinitalize方法、及び実行し、最終的に図に示されるであろう以下、例えば、すべてのクローズ機能を実行するためにされたとき、支持ネストされたトランザクションは、複数の方法が実行されます。順次実行wrapper1.initalize、wrapper2.initalize、anyMethod、wrapper1.close、wrapper2.close
そして、トランザクションが終了に反応し、それをどのように適用されますか?次のコードを通して私たちのトランザクションを使用する方法を参照するには
var ReactUpdates = require('ReactUpdates');
var Transaction = require('Transaction');
var emptyFunction = require('emptyFunction');
//第二个wrapper
var RESET_BATCHED_UPDATES = {
initialize: emptyFunction,
close: function() {
ReactDefaultBatchingStrategy.isBatchingUpdates = false;
},
};
//第一个wrapper
var FLUSH_BATCHED_UPDATES = {
initialize: emptyFunction,
close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates),
};
//wrapper列表
var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];
//事务构造函数
function ReactDefaultBatchingStrategyTransaction() {
//原型中定义的初始化方法
this.reinitializeTransaction();
}
//继承原型
Object.assign(
ReactDefaultBatchingStrategyTransaction.prototype,
Transaction.Mixin,
{
getTransactionWrappers: function() {
return TRANSACTION_WRAPPERS;
},
}
);
//新建一个事务
var transaction = new ReactDefaultBatchingStrategyTransaction();
var ReactDefaultBatchingStrategy = {
isBatchingUpdates: false,
/**
* Call the provided function in a context within which calls to `setState`
* and friends are batched such that components aren't updated unnecessarily.
*/
batchedUpdates: function(callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
// The code is written this way to avoid extra allocations
if (alreadyBatchingUpdates) {
callback(a, b, c, d, e);
} else {
//在这个地方调用事务,callback是从外部传入的方法,此处无需关心callback,只需要知道它是一个待执行方法即可
transaction.perform(callback, null, a, b, c, d, e);
}
},
};
コードは長くはありませんが、彼らは、我々は上記のコードは、コールReactDefaultBatchingStrategyTransactionを定義していることがわかります、行ってコードを気にしないだけでトランザクションを使用することを示すために、ここで最も重要なコードに反応するレンダリングロジックを制御するために使用されていますコンストラクタが、これは私たちのカスタム実際に取引され、プロトタイプのコンストラクタインターフェイスと呼ばれるgetTransactionWrappersに実装、このインタフェースのコードは配列を返す、各項目の配列はinitalizeが含まれています呼び出されたメソッドを実行したときとcloseメソッド、トランザクションは、これら2つのメソッドを呼び出すことになります、と私たちはreinitializeTransactionを見る方法は、メソッドを実行すると、コンストラクタが内部実装を提供Transaction.Mixin、で定義されていますすべての企業が基本的な機能を必要とする、我々は実装ロジックソースコードを見ることができます
'use strict';
var invariant = require('invariant');
var Mixin = {
//事务初始化函数
reinitializeTransaction: function() {
this.transactionWrappers = this.getTransactionWrappers();
if (this.wrapperInitData) {
this.wrapperInitData.length = 0;
} else {
this.wrapperInitData = [];
}
this._isInTransaction = false;
},
_isInTransaction: false,
//抽象接口,此处的getTransactionWrappers方法将会被外部定义的getTransactionWrappers方法所覆盖
getTransactionWrappers: null,
isInTransaction: function() {
return !!this._isInTransaction;
},
perform: function(method, scope, a, b, c, d, e, f) {
var errorThrown;
var ret;
try {
this._isInTransaction = true;
errorThrown = true;
//执行所有的initalize方法
this.initializeAll(0);
//执行真正的方法
ret = method.call(scope, a, b, c, d, e, f);
errorThrown = false;
} finally {
try {
if (errorThrown) {
try {
this.closeAll(0);
} catch (err) {
}
} else {
//正常状态下执行所有close方法
this.closeAll(0);
}
} finally {
this._isInTransaction = false;
}
}
return ret;
},
//执行所有wrapper中的initialize函数
initializeAll: function(startIndex) {
var transactionWrappers = this.transactionWrappers;
for (var i = startIndex; i < transactionWrappers.length; i++) {
var wrapper = transactionWrappers[i];
try {
//定义一个初始值,当finally里面匹配到this.wrapperInitData[i]未改变时,会忽略此项,从下一个项开始重新执行一次初始化,这么做的原因。。。官方解释为用catch使调试变的复杂,开心就好
this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;
//执行initialize方法
this.wrapperInitData[i] = wrapper.initialize ?
wrapper.initialize.call(this) :
null;
} finally {
if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {
try {
this.initializeAll(i + 1);
} catch (err) {
}
}
}
}
},
//执行所有wrapper中的close函数
closeAll: function(startIndex) {
invariant(
this.isInTransaction(),
'Transaction.closeAll(): Cannot close transaction when none are open.'
);
var transactionWrappers = this.transactionWrappers;
for (var i = startIndex; i < transactionWrappers.length; i++) {
var wrapper = transactionWrappers[i];
var initData = this.wrapperInitData[i];
var errorThrown;
try {
//标记是否有执行异常,这么做的原因。。。官方解释为用catch使调试变的复杂,开心就好
errorThrown = true;
//执行close方法
if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {
wrapper.close.call(this, initData);
}
errorThrown = false;
} finally {
//存在异常异常
if (errorThrown) {
try {
this.closeAll(i + 1);
} catch (e) {
}
}
}
}
this.wrapperInitData.length = 0;
},
};
var Transaction = {
Mixin: Mixin,
OBSERVED_ERROR: {},
};
module.exports = Transaction;
これは、トランザクション全体のメカニズムを実装するコードで、カットしないで、ロジックは、非常に単純な非常に明確である、実際には、ここではプロトタイプモデルを使用することがあり、これはすべてのトランザクションの原型である、トランザクション内でカスタマイズして使用する方法を確認するために私たちの前に行いますreinitializeTransaction方法は、実際には、コア原則は抽象インタフェース、それはサブクラスにプロトタイプから継承されたサブクラスに包含されます(右、コンドームと呼ばれる)ラッパーのための店を持っているプロトタイプの定義は、ある、そこに見つけることができますすべての実行のメソッドの実装がtrueになるように定義される前と後に、我々は論理の方法を実行見ることができますが、すべてを実行するためにcloseAllを実行した後、それは最初のinitializeメソッドのすべてを行う方法をでInitializeAll呼び出し、そのメソッドの入ってくる身体を実行することで、実際には非常に明確ですcloseメソッドは、したがって、それはそう、あなたが自分で見ることができ、関心のノートを追加したエントリを強制する方法の実装は、輸出法に追加される前に、コードが比較的単純で、ある深遠な視覚的なもの、ではありません
そして、比較的サンパウロ操作がついに公式ことで例外を処理するメソッドを使用し、キャッチ法により放棄され、現在実行中の処理が異常であるマークする一時的な変数を使用している、どんなにでInitializeAllかにcloseAllでは、ということですがあります引数が間違ったキャプチャはデバッグが困難になり、プロトタイプクラスをベースとして、ので、特別な理由があるべきであるここに入ってくる外部メソッドが例外をスローキャプチャするために行くべきではない、例外が直接外部関数の裁量外に投げ返ささせるべきですここで例外をキャッチするように強制した場合、外部関数のデバッグがより困難になる原因ありません