Authored by 李奇

Merge remote-tracking branch 'origin/master' into feature/data-report

# Conflicts:
#	src/app.js
@@ -178,7 +178,7 @@ class App extends Component { @@ -178,7 +178,7 @@ class App extends Component {
178 console.log(error); 178 console.log(error);
179 }); 179 });
180 180
181 - event.on('user-is-login', (loginedCallBack, loginSuccess) => { 181 + event.one('user-is-login', (loginedCallBack, loginSuccess) => {
182 let userInfo = Taro.getStorageSync('userInfo'); 182 let userInfo = Taro.getStorageSync('userInfo');
183 if (userInfo && userInfo.uid) { 183 if (userInfo && userInfo.uid) {
184 checkUidAndSessionKey(userInfo.uid, userInfo.session_key).then(result => { 184 checkUidAndSessionKey(userInfo.uid, userInfo.session_key).then(result => {
@@ -189,8 +189,7 @@ class App extends Component { @@ -189,8 +189,7 @@ class App extends Component {
189 loginedCallBack(); 189 loginedCallBack();
190 } 190 }
191 } else { 191 } else {
192 - event.on('my-user-login-success', () => {  
193 - event.off('my-user-login-success'); 192 + event.one('my-user-login-success', () => {
194 if (loginSuccess) { 193 if (loginSuccess) {
195 loginSuccess(); 194 loginSuccess();
196 } 195 }
@@ -214,8 +213,7 @@ class App extends Component { @@ -214,8 +213,7 @@ class App extends Component {
214 loginedCallBack(); 213 loginedCallBack();
215 } 214 }
216 } else { 215 } else {
217 - event.on('my-user-login-success', () => {  
218 - event.off('my-user-login-success'); 216 + event.one('my-user-login-success', () => {
219 if (loginSuccess) { 217 if (loginSuccess) {
220 loginSuccess(); 218 loginSuccess();
221 } 219 }
@@ -231,8 +229,7 @@ class App extends Component { @@ -231,8 +229,7 @@ class App extends Component {
231 loginedCallBack(); 229 loginedCallBack();
232 } 230 }
233 } else { 231 } else {
234 - event.on('my-user-login-success', () => {  
235 - event.off('my-user-login-success'); 232 + event.one('my-user-login-success', () => {
236 if (loginSuccess) { 233 if (loginSuccess) {
237 loginSuccess(); 234 loginSuccess();
238 } 235 }
@@ -249,8 +246,7 @@ class App extends Component { @@ -249,8 +246,7 @@ class App extends Component {
249 loginedCallBack(); 246 loginedCallBack();
250 } 247 }
251 } else { 248 } else {
252 - event.on('my-user-login-success', () => {  
253 - event.off('my-user-login-success'); 249 + event.one('my-user-login-success', () => {
254 if (loginSuccess) { 250 if (loginSuccess) {
255 loginSuccess(); 251 loginSuccess();
256 } 252 }
@@ -261,8 +257,7 @@ class App extends Component { @@ -261,8 +257,7 @@ class App extends Component {
261 } 257 }
262 }); 258 });
263 } else { 259 } else {
264 - event.on('my-user-login-success', () => {  
265 - event.off('my-user-login-success'); 260 + event.one('my-user-login-success', () => {
266 if (loginSuccess) { 261 if (loginSuccess) {
267 loginSuccess(); 262 loginSuccess();
268 } 263 }
@@ -273,7 +268,7 @@ class App extends Component { @@ -273,7 +268,7 @@ class App extends Component {
273 } 268 }
274 }); 269 });
275 270
276 - event.on('judge-user-is-login', (isLogined, isLoginCallback) => { 271 + event.one('judge-user-is-login', (isLogined, isLoginCallback) => {
277 let userInfo = Taro.getStorageSync('userInfo'); 272 let userInfo = Taro.getStorageSync('userInfo');
278 if (userInfo && userInfo.uid) { 273 if (userInfo && userInfo.uid) {
279 checkUidAndSessionKey(userInfo.uid, userInfo.session_key).then(result => { 274 checkUidAndSessionKey(userInfo.uid, userInfo.session_key).then(result => {
@@ -83,7 +83,7 @@ export default class Login extends Component { @@ -83,7 +83,7 @@ export default class Login extends Component {
83 83
84 eventOnAll() { 84 eventOnAll() {
85 const prefix = 'phonenumber'; 85 const prefix = 'phonenumber';
86 - event.on(this.addPrefix(prefix, USER_GET_PHONENUMBER_ERROR), (errMsg) => { 86 + event.one(this.addPrefix(prefix, USER_GET_PHONENUMBER_ERROR), (errMsg) => {
87 if (errMsg === 'getPhoneNumber:fail user deny') { 87 if (errMsg === 'getPhoneNumber:fail user deny') {
88 errMsg = '获取手机号失败,请使用验证码登录'; 88 errMsg = '获取手机号失败,请使用验证码登录';
89 } 89 }
@@ -93,13 +93,13 @@ export default class Login extends Component { @@ -93,13 +93,13 @@ export default class Login extends Component {
93 icon: 'none' 93 icon: 'none'
94 }); 94 });
95 }); 95 });
96 - event.on(this.addPrefix(prefix, USER_LOGIN_CALLBACK), (error) => { 96 + event.one(this.addPrefix(prefix, USER_LOGIN_CALLBACK), (error) => {
97 console.log(error); 97 console.log(error);
98 }); 98 });
99 - event.on(this.addPrefix(prefix, USER_LOGIN_SUCCESS), () => { 99 + event.one(this.addPrefix(prefix, USER_LOGIN_SUCCESS), () => {
100 this.redirectAction(); 100 this.redirectAction();
101 }); 101 });
102 - event.on(this.addPrefix(prefix, USER_CHANGE_LOGIN_STATUS), (message) => { 102 + event.one(this.addPrefix(prefix, USER_CHANGE_LOGIN_STATUS), (message) => {
103 const union_id = wx.getStorageSync('unionid'); 103 const union_id = wx.getStorageSync('unionid');
104 this.setState({ 104 this.setState({
105 inviteCode: this.$router.params.inviteCode ? this.$router.params.inviteCode : '', 105 inviteCode: this.$router.params.inviteCode ? this.$router.params.inviteCode : '',
@@ -17,19 +17,19 @@ Page({ @@ -17,19 +17,19 @@ Page({
17 */ 17 */
18 onLoad: function (options) { 18 onLoad: function (options) {
19 let that = this; 19 let that = this;
20 - event.on('user-login-success', () => { 20 + event.one('user-login-success', () => {
21 // 返回上一页 21 // 返回上一页
22 this.goReferer(); // 如果不需要绑定手机则返回前一页 22 this.goReferer(); // 如果不需要绑定手机则返回前一页
23 }); 23 });
24 - event.on('change-login-status', params => { 24 + event.one('change-login-status', params => {
25 that.setData({ 25 that.setData({
26 loginText: params.text || '微信登录', 26 loginText: params.text || '微信登录',
27 loginTips: params.tips || '', 27 loginTips: params.tips || '',
28 loginButtonType: params.openType || '' 28 loginButtonType: params.openType || ''
29 }); 29 });
30 }); 30 });
31 - event.on('user-login-callback', this.loginCallback);  
32 - event.on('user-get-phonenumber-error', this.getPhonenumberError); 31 + event.one('user-login-callback', this.loginCallback);
  32 + event.one('user-get-phonenumber-error', this.getPhonenumberError);
33 }, 33 },
34 34
35 getPhonenumberError(error) { 35 getPhonenumberError(error) {
@@ -96,7 +96,8 @@ Page({ @@ -96,7 +96,8 @@ Page({
96 * 生命周期函数--监听页面卸载 96 * 生命周期函数--监听页面卸载
97 */ 97 */
98 onUnload: function () { 98 onUnload: function () {
99 - 99 + event.remove('user-login-callback', this.loginCallback);
  100 + event.remove('user-get-phonenumber-error', this.getPhonenumberError);
100 }, 101 },
101 102
102 /** 103 /**
@@ -56,7 +56,7 @@ Page({ @@ -56,7 +56,7 @@ Page({
56 that.fetchOrderList(2,1); 56 that.fetchOrderList(2,1);
57 } 57 }
58 }); 58 });
59 - event.on('refresh-order', () => { 59 + event.one('refresh-order', () => {
60 // console.log("======refresh-order") 60 // console.log("======refresh-order")
61 let currentType = that.data.activeIndex + 2; 61 let currentType = that.data.activeIndex + 2;
62 this.fetchOrderList(currentType,1); 62 this.fetchOrderList(currentType,1);
1 -export default {  
2 - listeners: [],  
3 - on(type, handle) {  
4 - // first remove and add  
5 - this.off(type, handle);  
6 -  
7 - if (typeof handle === 'function') {  
8 - console.debug(`listen event ${type}`);  
9 - this.listeners.push([type, handle]);  
10 - }  
11 - },  
12 - off(type, handle) {  
13 - let index = -1;  
14 -  
15 - if (typeof handle === 'function' &&  
16 - this.listeners.some(([itype, ihandle]) => {  
17 - index++;  
18 - return itype === type && handle.name && ihandle.name === handle.name;  
19 - })  
20 - ) {  
21 - this.listeners.splice(index, 1);  
22 - }  
23 - },  
24 - emit(type, ...params) {  
25 - this.listeners.forEach(([listenType, handle]) => type === listenType && handle(...params));  
26 - console.debug(`receive event ${type}: ${JSON.stringify(params)}`);  
27 - },  
28 - removeAllListeners() {  
29 - this.listeners = [];  
30 - }  
31 -}; 1 +/**
  2 + * description: 参考借鉴 Node.js 的 EventEmitter
  3 + * 对象管理 event 事件
  4 + * @func on 监听
  5 + * @func emit 触发
  6 + * @func once 监听只执行一次
  7 + * @func remove 移除某个类型的某个事件
  8 + * @func removeAll 移除某个类型的全部事件/所有类型的全部事件
  9 + */
  10 +class EventEmitter {
  11 + constructor() {
  12 + this._events = Object.create(null);
  13 + this._eventsCount = 0;
  14 + }
  15 +
  16 + /**
  17 + * emit 触发事件
  18 + * @param type 事件名
  19 + * @param ...args 参数
  20 + */
  21 + emit(type) {
  22 + let events, handler, len, isFn;
  23 +
  24 + events = this._events;
  25 + handler = events[type];
  26 + console.log(events);
  27 +
  28 + if (!handler)
  29 + return false;
  30 +
  31 + isFn = typeof handler === 'function';
  32 + len = arguments.length;
  33 +
  34 + // 优化性能
  35 + switch(len) {
  36 + case 0:
  37 + throw new Error('"emit" not have arguments');
  38 + break;
  39 + case 1:
  40 + emitNone(handler, isFn, this);
  41 + break;
  42 + case 2:
  43 + emitOne(handler, isFn, this, arguments[1]);
  44 + break;
  45 + case 3:
  46 + emitTwo(handler, isFn, this, arguments[1], arguments[2]);
  47 + break;
  48 + case 4:
  49 + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
  50 + break;
  51 + default:
  52 + args = new Array(len - 1);
  53 + for (let i = 1; i < len; i++) {
  54 + args[i - 1] = arguments[i];
  55 + }
  56 + emitMany(handler, isFn, this, args);
  57 + }
  58 +
  59 + return true;
  60 + }
  61 +
  62 + one(type, listener,) {
  63 + let events;
  64 + if (typeof listener !== 'function')
  65 + throw new Error('"listener" argument must be a function');
  66 +
  67 + events = this._events;
  68 + console.log(events);
  69 + if (typeof events === 'undefined') {
  70 + events = this._events = Object.create(null);
  71 + this._eventsCount = 0;
  72 + }
  73 +
  74 + events[type] = listener;
  75 + ++this._eventsCount;
  76 + return this;
  77 + }
  78 +
  79 + _addListener(type, listener, prepend) {
  80 + let events;
  81 + let existing;
  82 + if (typeof listener !== 'function')
  83 + throw new Error('"listener" argument must be a function');
  84 +
  85 + events = this._events;
  86 + console.log(events);
  87 +
  88 + if (typeof events === 'undefined') {
  89 + events = this._events = Object.create(null);
  90 + this._eventsCount = 0;
  91 + } else {
  92 + existing = events[type];
  93 + }
  94 +
  95 + if (!existing) {
  96 + existing = events[type] = listener;
  97 + ++this._eventsCount;
  98 + } else {
  99 + if (typeof existing === 'function') {
  100 + existing = events[type] = prepend ? [listener, existing] : [existing, listener];
  101 + } else if (prepend) {
  102 + existing.unshift(listener);
  103 + } else {
  104 + existing.push(listener);
  105 + }
  106 + }
  107 +
  108 + return this;
  109 + }
  110 +
  111 + /**
  112 + * on 监听事件
  113 + * @param type 事件名
  114 + * @param listener 监听函数
  115 + */
  116 + on(type, listener) {
  117 + return this._addListener(type, listener, false);
  118 + }
  119 +
  120 + /**
  121 + * once 监听只执行一次事件
  122 + * @param type 事件名
  123 + * @param listener 只执行一次的监听函数
  124 + */
  125 + once(type, listener) {
  126 + if (typeof listener !== 'function')
  127 + throw new Error('"listener" argument must be a function');
  128 + this.on(type, _onceWrap(this, type, listener));
  129 + return this;
  130 + }
  131 +
  132 + /**
  133 + * prepend 优先监听事件
  134 + * @param type 事件名
  135 + * @param listener 要优先的监听函数
  136 + */
  137 + prepend(type, listener) {
  138 + return this._addListener(type, listener, true);
  139 + }
  140 +
  141 + /**
  142 + * prependOnce 优先只执行一次的监听事件
  143 + * @param type 事件名
  144 + * @param listener 要优先且只执行一次的监听函数
  145 + */
  146 + prependOnce(type, listener) {
  147 + if (typeof listener !== 'function')
  148 + throw new TypeError('"listener" argument must be a function');
  149 + this.prepend(type, _onceWrap(this, type, listener));
  150 + return this;
  151 + }
  152 +
  153 + /**
  154 + * remove 移除的监听事件
  155 + * @param type 事件名
  156 + * @param listener 要移除的监听函数(可选)
  157 + */
  158 + remove(type, listener) {
  159 + let list, events, position, originalListener;
  160 +
  161 + if (typeof listener !== 'function')
  162 + throw new TypeError('"listener" argument must be a function');
  163 +
  164 + events = this._events;
  165 + if (!events) {
  166 + return this;
  167 + }
  168 +
  169 + list = events[type];
  170 + if (!list) {
  171 + return this;
  172 + }
  173 +
  174 + if (list === listener || list.listener === listener) {
  175 + if (--this._eventsCount === 0) {
  176 + this._events = Object.create(null);
  177 + } else {
  178 + delete events[type];
  179 + }
  180 + } else if (typeof list !== 'function') {
  181 + position = -1;
  182 +
  183 + for (let i = list.length - 1; i >= 0; i--) {
  184 + if (list[i] === listener || list[i].listener === listener) {
  185 + originalListener = list[i].listener;
  186 + position = i;
  187 + break;
  188 + }
  189 + }
  190 +
  191 + if (position < 0) {
  192 + return this;
  193 + }
  194 +
  195 + if (position === 0) {
  196 + list.shift();
  197 + } else {
  198 + spliceOne(list, position);
  199 + }
  200 +
  201 + if (list.length === 1) {
  202 + events[type] = list[0];
  203 + }
  204 + }
  205 +
  206 + return this;
  207 + }
  208 +
  209 + /**
  210 + * removeAll 移除某事件名的全部监听事件/移除全部事件名的事件
  211 + * @param type 事件名
  212 + */
  213 + removeAll(type) {
  214 + let listeners, events;
  215 +
  216 + events = this._events;
  217 +
  218 + if (!events)
  219 + return this;
  220 +
  221 + if (arguments.length === 0) {
  222 + var keys = Object.keys(events);
  223 + var key;
  224 + for (let i = 0; i < keys.length; ++i) {
  225 + key = keys[i];
  226 + this.removeAll(key);
  227 + }
  228 + this._events = Object.create(null);
  229 + this._eventsCount = 0;
  230 + return this;
  231 + }
  232 +
  233 + listeners = events[type];
  234 +
  235 + if (typeof listeners === 'function') {
  236 + this.remove(type, listeners);
  237 + } else if (listeners !== undefined) {
  238 + for (let i = listeners.length - 1; i >= 0; i--) {
  239 + this.remove(type, listeners[i]);
  240 + }
  241 + }
  242 +
  243 + return this;
  244 + }
  245 +
  246 + eventNames() {
  247 + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
  248 + }
  249 +}
  250 +
  251 +
  252 +const emitNone = (handler, isFn, self) => {
  253 + if (isFn) {
  254 + handler.call(self);
  255 + } else {
  256 + let len = handler.length;
  257 + let listeners = arrayClone(handler, len);
  258 + for (let i = 0; i < len; ++i)
  259 + listeners[i].call(self);
  260 + }
  261 +}
  262 +
  263 +const emitOne = (handler, isFn, self, arg1) => {
  264 + if (isFn) {
  265 + handler.call(self, arg1);
  266 + } else {
  267 + let len = handler.length;
  268 + let listeners = arrayClone(handler, len);
  269 + for (let i = 0; i < len; ++i)
  270 + listeners[i].call(self, arg1);
  271 + }
  272 +}
  273 +
  274 +const emitTwo = (handler, isFn, self, arg1, arg2) => {
  275 + if (isFn) {
  276 + handler.call(self, arg1, arg2);
  277 + } else {
  278 + let len = handler.length;
  279 + let listeners = arrayClone(handler, len);
  280 + for (let i = 0; i < len; ++i)
  281 + listeners[i].call(self, arg1, arg2);
  282 + }
  283 +}
  284 +
  285 +const emitThree = (handler, isFn, self, arg1, arg2, arg3) => {
  286 + if (isFn) {
  287 + handler.call(self, arg1, arg2, arg3);
  288 + } else {
  289 + let len = handler.length;
  290 + let listeners = arrayClone(handler, len);
  291 + for (let i = 0; i < len; ++i)
  292 + listeners[i].call(self, arg1, arg2, arg3);
  293 + }
  294 +}
  295 +
  296 +const emitMany = (handler, isFn, self, args) => {
  297 + if (isFn) {
  298 + handler.apply(self, args);
  299 + } else {
  300 + let len = handler.length;
  301 + let listeners = arrayClone(handler, len);
  302 + for (let i = 0; i < len; ++i)
  303 + listeners[i].apply(self, args);
  304 + }
  305 +}
  306 +
  307 +const spliceOne = (list, index) => {
  308 + for (; index + 1 < list.length; index++)
  309 + list[index] = list[index + 1];
  310 + list.pop();
  311 +}
  312 +
  313 +function onceWrapper(...args) {
  314 + if (!this.fired) {
  315 + this.target.remove(this.type, this.wrapFn);
  316 + this.fired = true;
  317 + Reflect.apply(this.listener, this.target, args);
  318 + }
  319 +}
  320 +
  321 +const _onceWrap = (target, type, listener) => {
  322 + var state = { fired: false, wrapFn: undefined, target, type, listener };
  323 + var wrapped = onceWrapper.bind(state);
  324 + wrapped.listener = listener;
  325 + state.wrapFn = wrapped;
  326 + return wrapped;
  327 +}
  328 +
  329 +function arrayClone(arr, n) {
  330 + var copy = new Array(n);
  331 + for (var i = 0; i < n; ++i)
  332 + copy[i] = arr[i];
  333 + return copy;
  334 +}
  335 +
  336 +const event = new EventEmitter();
  337 +
  338 +export default event;