通量事件发射器
Flux eventemitter
我目前正在尝试 FLUX 设计模式,但我遇到了一个问题。在这个项目中,我也使用 ReactJS 来配合它。它工作得很好,快要完成了,但搞砸了。所以我用我渲染的按钮启动函数,点击它会触发函数链。
render: function(){
return (
<div><button onClick={this.waiting}>Hello</button>
{this.state.results}
</div>
)
}
您现在可以看到,当单击此按钮时,它会触发一个名为 waiting() 的函数,其中包含以下内容
waiting: function() {
actions.trending();
return this.state.results;
},
因此它触发函数并发生以下情况
var actions = {
trending: function(){
api.trending()
.then(function(result){
dispatcher.dispatch({
actionType: actionConstants.TRENDING_RESULT,
results: result
});
}, function(error){
console.log(error);
dispatcher.dispatch({
actionType: actionConstants.ERROR,
error: error
});
});
}
};
一切正常,我正在获取我的数据,到目前为止我很高兴,问题是接下来会发生什么,当调度程序将 actionType 与数据一起调度时,它会进入我拥有的商店。然后在我的存储文件中注册有效负载(操作)。
dispatcher.register(function(action){
switch (action.actionType) {
case actionConstants.TRENDING_RESULT:
console.log(action.results); <- I can actually see my data
results = action.results;
resultErrors = null;
SearchStore.emit(actionConstants.TRENDING_RESULT); <- Error
break;
case actionConstants.ERROR:
results = null;
resultErrors = action.error;
console.log(resultErrors);
SearchStore.emit(actionsConstants.ERROR);
break;
}
});
所以此时我可以在 console.log 中看到我的数据,但是我在 emit 函数中收到一个错误,听起来如下
Uncaught (in promise) TypeError: this._events[evt].push
对于我的商店功能,我使用以下内容
var SearchStore = {
getTrending: function() {
return JSON.stringify(results);
},
getError: function() {
return resultErrors;
},
emit: function(event) {
eventEmitter.on(event);
},
on: function(event, callback) {
eventEmitter.on(event, callback);
},
removeListener: function(event, callback) {
eventEmitter.removeListener(event, callback);
}
};
最后为了接收任何发射,我在 ComponentDidMount 中调用我的 on 函数,看起来像这样
componentDidMount: function(){
SearchStore.on(actionConstants.TRENDING_RESULT, this.loadResults());
SearchStore.on(actionConstants.ERROR, this.showError());
},
componentWillUnmount: function(){
SearchStore.removeListener(actionConstants.TRENDING_RESULT, this.loadResults());
SearchStore.removeListener(actionConstants.ERROR, this.showError());
},
对于 Dispatcher,我使用 Facebook 的 FLUX dispatcher,对于发射器,我使用 eventemitter3。直到我尝试发出 TRENDING_RESULT 和它的有效载荷之前,一切都进行得很顺利。对于这个问题的长度,我感到非常抱歉,但我想尽可能全面地让您理解。
事件发射器应该调用 emit 函数而不是 on 函数。
所以它应该是这样的:
var SearchStore = {
getTrending: function() {
return JSON.stringify(results);
},
getError: function() {
return resultErrors;
},
emit: function(event) {
eventEmitter.emit(event); // HERE!!
},
on: function(event, callback) {
eventEmitter.on(event, callback);
},
removeListener: function(event, callback) {
eventEmitter.removeListener(event, callback);
}
};
我的解决方案如下:
'use strict';
var dispatcher = require('../dispatcher/dispatcher');
var EventEmitter = require('events').EventEmitter;
var ObjectAssign = require('object-assign');
var actionConstants = require('../constants/actionConstants');
var _store = {
list: [],
error: [],
genres: [],
playlists: []
}
var resultErrors = null;
var CHANGE_EVENT = 'change';
var SearchStore = ObjectAssign( {}, EventEmitter.prototype, {
getTrending: function() {
return _store;
},
getError: function() {
return _store;
},
addChangeListener: function(callback){
this.on(CHANGE_EVENT, callback);
},
removeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getGenres: function() {
return _store;
},
getPlaylists: function() {
return _store;
}
});
dispatcher.register(function(action){
switch (action.actionType) {
case actionConstants.TRENDING_RESULT:
action.results.map(function(item){
_store.list.push(item);
});
resultErrors = null;
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.SEARCH_RESULT:
_store.list = [];
console.log(_store.list);
action.results.map(function(item){
_store.list.push(item);
});
resultErrors = null;
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.ERROR:
results = null;
_store.error.push(action.error);
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.ADD_GENRE:
_store.genres.push(action.index);
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.REMOVE_GENRE:
_store.genres = _store.genres.filter(function(index){
return index !== action.index;
});
console.log(_store.genres);
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.SAVE_PLAYLIST:
var playlists = {
"name": action.index,
"items": {}
}
;
_store.playlists.push(playlists);
SearchStore.emit(CHANGE_EVENT);
break;
default:
}
});
所以我一起删除了我的 "emit" 和 "on" 函数并制作了一个 addChangeListener。所以我直接从我的 switch cases 发出,因为 "emit" 已经是一个函数,所以我不需要为 "emit" 函数创建一个函数。我只是使用我的侦听器接收 CHANGE_EVENT,然后它会 运行 一个回调函数。示例:
componentDidMount: function(){
SearchStore.addChangeListener(this.loadPlaylists);
},
componentWillUnmount: function(){
SearchStore.removeListener(this.loadPlaylists);
},
现在它运行得很好,我明白如果我只是仔细查看我的代码我就可以省去麻烦但是你学得越多对吗?无论如何再次感谢你的时间。
我目前正在尝试 FLUX 设计模式,但我遇到了一个问题。在这个项目中,我也使用 ReactJS 来配合它。它工作得很好,快要完成了,但搞砸了。所以我用我渲染的按钮启动函数,点击它会触发函数链。
render: function(){
return (
<div><button onClick={this.waiting}>Hello</button>
{this.state.results}
</div>
)
}
您现在可以看到,当单击此按钮时,它会触发一个名为 waiting() 的函数,其中包含以下内容
waiting: function() {
actions.trending();
return this.state.results;
},
因此它触发函数并发生以下情况
var actions = {
trending: function(){
api.trending()
.then(function(result){
dispatcher.dispatch({
actionType: actionConstants.TRENDING_RESULT,
results: result
});
}, function(error){
console.log(error);
dispatcher.dispatch({
actionType: actionConstants.ERROR,
error: error
});
});
}
};
一切正常,我正在获取我的数据,到目前为止我很高兴,问题是接下来会发生什么,当调度程序将 actionType 与数据一起调度时,它会进入我拥有的商店。然后在我的存储文件中注册有效负载(操作)。
dispatcher.register(function(action){
switch (action.actionType) {
case actionConstants.TRENDING_RESULT:
console.log(action.results); <- I can actually see my data
results = action.results;
resultErrors = null;
SearchStore.emit(actionConstants.TRENDING_RESULT); <- Error
break;
case actionConstants.ERROR:
results = null;
resultErrors = action.error;
console.log(resultErrors);
SearchStore.emit(actionsConstants.ERROR);
break;
}
});
所以此时我可以在 console.log 中看到我的数据,但是我在 emit 函数中收到一个错误,听起来如下
Uncaught (in promise) TypeError: this._events[evt].push
对于我的商店功能,我使用以下内容
var SearchStore = {
getTrending: function() {
return JSON.stringify(results);
},
getError: function() {
return resultErrors;
},
emit: function(event) {
eventEmitter.on(event);
},
on: function(event, callback) {
eventEmitter.on(event, callback);
},
removeListener: function(event, callback) {
eventEmitter.removeListener(event, callback);
}
};
最后为了接收任何发射,我在 ComponentDidMount 中调用我的 on 函数,看起来像这样
componentDidMount: function(){
SearchStore.on(actionConstants.TRENDING_RESULT, this.loadResults());
SearchStore.on(actionConstants.ERROR, this.showError());
},
componentWillUnmount: function(){
SearchStore.removeListener(actionConstants.TRENDING_RESULT, this.loadResults());
SearchStore.removeListener(actionConstants.ERROR, this.showError());
},
对于 Dispatcher,我使用 Facebook 的 FLUX dispatcher,对于发射器,我使用 eventemitter3。直到我尝试发出 TRENDING_RESULT 和它的有效载荷之前,一切都进行得很顺利。对于这个问题的长度,我感到非常抱歉,但我想尽可能全面地让您理解。
事件发射器应该调用 emit 函数而不是 on 函数。 所以它应该是这样的:
var SearchStore = {
getTrending: function() {
return JSON.stringify(results);
},
getError: function() {
return resultErrors;
},
emit: function(event) {
eventEmitter.emit(event); // HERE!!
},
on: function(event, callback) {
eventEmitter.on(event, callback);
},
removeListener: function(event, callback) {
eventEmitter.removeListener(event, callback);
}
};
我的解决方案如下:
'use strict';
var dispatcher = require('../dispatcher/dispatcher');
var EventEmitter = require('events').EventEmitter;
var ObjectAssign = require('object-assign');
var actionConstants = require('../constants/actionConstants');
var _store = {
list: [],
error: [],
genres: [],
playlists: []
}
var resultErrors = null;
var CHANGE_EVENT = 'change';
var SearchStore = ObjectAssign( {}, EventEmitter.prototype, {
getTrending: function() {
return _store;
},
getError: function() {
return _store;
},
addChangeListener: function(callback){
this.on(CHANGE_EVENT, callback);
},
removeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getGenres: function() {
return _store;
},
getPlaylists: function() {
return _store;
}
});
dispatcher.register(function(action){
switch (action.actionType) {
case actionConstants.TRENDING_RESULT:
action.results.map(function(item){
_store.list.push(item);
});
resultErrors = null;
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.SEARCH_RESULT:
_store.list = [];
console.log(_store.list);
action.results.map(function(item){
_store.list.push(item);
});
resultErrors = null;
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.ERROR:
results = null;
_store.error.push(action.error);
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.ADD_GENRE:
_store.genres.push(action.index);
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.REMOVE_GENRE:
_store.genres = _store.genres.filter(function(index){
return index !== action.index;
});
console.log(_store.genres);
SearchStore.emit(CHANGE_EVENT);
break;
case actionConstants.SAVE_PLAYLIST:
var playlists = {
"name": action.index,
"items": {}
}
;
_store.playlists.push(playlists);
SearchStore.emit(CHANGE_EVENT);
break;
default:
}
});
所以我一起删除了我的 "emit" 和 "on" 函数并制作了一个 addChangeListener。所以我直接从我的 switch cases 发出,因为 "emit" 已经是一个函数,所以我不需要为 "emit" 函数创建一个函数。我只是使用我的侦听器接收 CHANGE_EVENT,然后它会 运行 一个回调函数。示例:
componentDidMount: function(){
SearchStore.addChangeListener(this.loadPlaylists);
},
componentWillUnmount: function(){
SearchStore.removeListener(this.loadPlaylists);
},
现在它运行得很好,我明白如果我只是仔细查看我的代码我就可以省去麻烦但是你学得越多对吗?无论如何再次感谢你的时间。