admin管理员组文章数量:1321443
I am implementing Pusher into my React+Redux Saga application, but I am having a few problems with some callbacks where I can not hit the put(...)
methods. Using console.log(...)
etc. in the methods does show, but I am not able to put
to the state of my application.
I could be wrong on some of the implementation of async/generator functions, but I am pretty much stuck right now.
My code to illustrate what will not fire:
import { takeLatest } from 'redux-saga'
import { call, put } from 'redux-saga/effects'
// Pusher actions
export const pusherConnecting = () => {
return {
type: ActionTypes.PUSHER_CONNECTING
}
};
export const pusherConnectSucceeded = (client) => {
return {
type: ActionTypes.PUSHER_CONNECT_SUCCEEDED,
client: client
}
};
const pusherConnectFailed = (exception) => {
return {
type: ActionTypes.PUSHER_CONNECT_FAILED,
message: exception
}
};
// Pusher Saga
function * connectPusher(action) {
try {
const pusher = yield call(Api.connectPusher, action.directory, function(subscription) {
subscription.bind(PUSHER_BIND_RELOAD, function() {
location.reload(true);
});
subscription.bind(PUSHER_BIND_REQUEST_DATA, function(data) {
if (data) {
put(updateDirectory(data));
} else {
put(requestDirectory(action.directory.id));
}
});
});
pusher.connection.bind('connected', function() {
put(pusherConnectSucceeded(pusher));
});
yield put(pusherConnecting());
} catch (e) {
yield put(pusherConnectFailed(e));
}
}
export default function * pusherSaga() {
yield * takeLatest(ActionTypes.DIRECTORY_FETCH_SUCCEEDED, connectPusher);
}
// My Api.ConnectPusher
export function * connectPusher(directory, subscription) {
var pusher = new Pusher(PUSHER_KEY, {
encrypted: true
});
var channels = ["test1", "test2" ];
for (var i = 0; i < channels.length; i++) {
// Take each channel and callback with the subscription
yield subscription(pusher.subscribe(channels[i]));
}
return pusher;
}
Solution based on @Sebastien
yield put(yield onConnect(pusher));
function onConnect(pusher) {
return new Promise((resolve, reject) => {
pusher.connection.bind('connected', function() {
resolve(pusherConnectSucceeded(pusher));
});
});
}
I am implementing Pusher into my React+Redux Saga application, but I am having a few problems with some callbacks where I can not hit the put(...)
methods. Using console.log(...)
etc. in the methods does show, but I am not able to put
to the state of my application.
I could be wrong on some of the implementation of async/generator functions, but I am pretty much stuck right now.
My code to illustrate what will not fire:
import { takeLatest } from 'redux-saga'
import { call, put } from 'redux-saga/effects'
// Pusher actions
export const pusherConnecting = () => {
return {
type: ActionTypes.PUSHER_CONNECTING
}
};
export const pusherConnectSucceeded = (client) => {
return {
type: ActionTypes.PUSHER_CONNECT_SUCCEEDED,
client: client
}
};
const pusherConnectFailed = (exception) => {
return {
type: ActionTypes.PUSHER_CONNECT_FAILED,
message: exception
}
};
// Pusher Saga
function * connectPusher(action) {
try {
const pusher = yield call(Api.connectPusher, action.directory, function(subscription) {
subscription.bind(PUSHER_BIND_RELOAD, function() {
location.reload(true);
});
subscription.bind(PUSHER_BIND_REQUEST_DATA, function(data) {
if (data) {
put(updateDirectory(data));
} else {
put(requestDirectory(action.directory.id));
}
});
});
pusher.connection.bind('connected', function() {
put(pusherConnectSucceeded(pusher));
});
yield put(pusherConnecting());
} catch (e) {
yield put(pusherConnectFailed(e));
}
}
export default function * pusherSaga() {
yield * takeLatest(ActionTypes.DIRECTORY_FETCH_SUCCEEDED, connectPusher);
}
// My Api.ConnectPusher
export function * connectPusher(directory, subscription) {
var pusher = new Pusher(PUSHER_KEY, {
encrypted: true
});
var channels = ["test1", "test2" ];
for (var i = 0; i < channels.length; i++) {
// Take each channel and callback with the subscription
yield subscription(pusher.subscribe(channels[i]));
}
return pusher;
}
Solution based on @Sebastien
yield put(yield onConnect(pusher));
function onConnect(pusher) {
return new Promise((resolve, reject) => {
pusher.connection.bind('connected', function() {
resolve(pusherConnectSucceeded(pusher));
});
});
}
Share
Improve this question
edited Jun 9, 2016 at 13:21
janhartmann
asked Jun 9, 2016 at 11:13
janhartmannjanhartmann
15k17 gold badges87 silver badges140 bronze badges
5
- What does "is not hit" mean? You don't reach that line? How are you checking, with a debugger? – T.J. Crowder Commented Jun 9, 2016 at 11:23
-
It means that I am unable to fire this method. The
put
method is not invoked in my anonymous method callback. Or maybe it is, but the state is not changing (which is my my question). – janhartmann Commented Jun 9, 2016 at 11:23 -
Why "maybe"? It seems like that would be a really fundamental thing to determine, whether
put
is not being reached or being reached but not having the desired effect. I'd use a debugger to follow what, exactly, happens, or (and this is very much a second-class option) throw in someconsole.log
s. (But pared to wandering about with aconsole.log
torch, using a debugger is like turning on the lights.) – T.J. Crowder Commented Jun 9, 2016 at 11:28 -
My problem is that e.g. the
put(pusherConnectSucceeded(pusher));
method does not dispatch a state change. Apperently it is not possible to callput(...)
inside an anonymous callback. – janhartmann Commented Jun 9, 2016 at 11:48 -
No, there's no way for
put
to know you're calling it from an anonymous callback, and even if there were, there's nothing special about anonymous callbacks. Again, you'll just need to debug this. – T.J. Crowder Commented Jun 9, 2016 at 11:53
1 Answer
Reset to default 8Redux-saga does not permit to put
without using keyword yield
. The put creates a simple json object/effect that must be interpreted/executed, and it won't if you don't yield.
Also, even with yield put(...)
, if this is done in a callback, it won't be interpreted, because Redux-saga does not have the ability to run callbacks in its interpreter. They'll simply be run as normal callbacks and nothing will happen.
If subscription.bind
is supposed to return a single result, you can instead wrap that call into a function that returns a promise, and then yield that promise.
If subscription.bind
is supposed to return a stream of results, you might need instead of create a channel. I guess in the future someone will ship something that can easily permits to transform Observables to Redux-saga streams
Note that if you don't need to unsubscribe/resubscribe multiple times, it may be simpler to you to put this code outside the saga, and just do
subscription.bind(PUSHER_BIND_RELOAD, function() {
location.reload(true);
});
subscription.bind(PUSHER_BIND_REQUEST_DATA, function(data) {
if (data) {
reduxStore.dispatch(updateDirectory(data));
} else {
reduxStore.dispatch((requestDirectory(action.directory.id));
}
});
本文标签: javascriptUsing put inside anonymous function callbackStack Overflow
版权声明:本文标题:javascript - Using put inside anonymous function callback - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742101459a2420820.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论