再一次,javascript设计模式与开发实践-观察者模式

简述

又叫发布-订阅模式,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知。

这是一个很常见也很实用的模式,例如click事件就是一个典型的观察者模式。

使用场景

  • 登录
  • 订餐
  • ..

案例

假如我们在开发的网页中的某些模块需要在用户登录成功后才能开始渲染。
用户什么时候登录无法得知,那么可以让每一个模块渲染完毕后订阅消息,等用户登录后发布每个订阅。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
var Event = (function () {
    var clientList = [],
        listen,
        trigger,
        remove;

    listen = function (key, fn) {
        var collect = clientList[key] || (clientList[key] = []);

        collect.push(fn);
    };


    trigger = function () {
        var key = [].shift.call(arguments),
            fns = clientList[key];

        if (!fns) return false;

        for (var i = 0, v; v = fns[i++];) {
            v.apply(this, arguments);
        }
    };

    remove = function (key, fn) {
        var fns = clientList[key];

        if (!fns) return false;

        if (!fn) return fns.length = 0;

        for (var i = 0, v; v = fns[i++];) {
            if (v === fn) return fns.splice(i - 1, 1);
        }
    };

    return {
        listen : listen,
        trigger: trigger,
        remove : remove
    }
})();

// 假如这是一个登录请求
var mockAjax = setTimeout(function () {
    Event.trigger('loginSucc');
}, 1500);

var header = (function () {
    Event.listen('loginSucc', function () {
        header.setAvatar();
    });

    return {
        setAvatar: function () {
            console.log('设置头像');
        }
    }
})();

var nav = (function () {
    Event.listen('loginSucc', function () {
        nav.setMenu();
    });

    return {
        setMenu: function () {
            console.log('设置菜单');
        }
    }
})();

PS:在真实案例中会存在这种情况:用户提前登录了,但模块并没有加载完毕,这种情况需要特别注意一下。