1/* 2 * Copyright (c) 2020 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import { ObserverStack, canObserve } from './utils'; 16 17/** 18 * Observer constructor 19 * @param {ViewModel} context execute context of callback 20 * @param {Function} getter getter function 21 * @param {Function} callback callback function 22 * @param {Object} meta meta data that Observer object don't care about 23 */ 24export function Observer(context, getter, callback, meta) { 25 this._ctx = context; 26 this._getter = getter; 27 this._fn = callback; 28 this._meta = meta; 29 this._lastValue = this._get(); 30} 31 32Observer.prototype._get = function() { 33 try { 34 ObserverStack.push(this); 35 return this._getter.call(this._ctx); 36 } finally { 37 ObserverStack.pop(); 38 } 39}; 40 41Observer.prototype.update = function() { 42 const lastValue = this._lastValue; 43 const nextValue = this._get(); 44 const context = this._ctx; 45 const meta = this._meta; 46 47 if (nextValue !== lastValue || canObserve(nextValue)) { 48 this._fn.call(context, nextValue, lastValue, meta); 49 this._lastValue = nextValue; 50 } 51}; 52 53Observer.prototype.subscribe = function(subject, key) { 54 const detach = subject.attach(key, this); 55 if (typeof detach !== 'function') { 56 return void 0; 57 } 58 if (!this._detaches) { 59 this._detaches = new Set(); 60 } 61 this._detaches.add(detach); 62 return void 1; 63}; 64 65Observer.prototype.unsubscribe = function() { 66 const detaches = this._detaches; 67 if (!detaches) { 68 return void 0; 69 } 70 detaches.forEach( detach => { 71 detach(); 72 }); 73 this._detaches.clear(); 74 return void 1; 75}; 76