2016-06-09 47 views
10

我在我的React + Redux Saga应用程序中实现了Pusher,但我遇到了一些回调的问题,我无法访问put(...)方法。在方法中使用console.log(...)等确实显示,但我不能put到我的应用程序的状态。使用放在匿名函数回调中

我可能在某些异步/生成器函数的实现上出错,但我现在几乎停滞不前。

我的代码究竟会不会火来说明:

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; 
} 

解决方案基于@Sebastien

yield put(yield onConnect(pusher)); 

function onConnect(pusher) { 
    return new Promise((resolve, reject) => { 
     pusher.connection.bind('connected', function() { 
      resolve(pusherConnectSucceeded(pusher)); 
     }); 
    }); 
} 
+0

什么是“不命中”是什么意思?你没有达到那条线?你如何用调试器检查? –

+0

这意味着我无法启动这个方法。 'put'方法不会在我的匿名方法回调中调用。或者,也许是这样,但是国家没有改变(这是我的问题)。 – janhartmann

+0

为什么“可能”?看起来这将是一个真正的**基本的事情来决定,是否达到或未达到,但没有达到预期的效果。我会使用一个调试器来跟踪发生的事情,或者(并且这是非常多的**二级选项)抛出一些'console.log'。 (但与使用'console.log'手电筒徘徊相比,使用调试器就像打开灯一样。) –

回答

6

终极版 - 传奇不允许以put不使用关键字yield。 put创建了一个简单的json对象/效果,必须被解释/执行,并且如果不屈服,它将不会产生。

此外,即使使用yield put(...),如果这是在回调中完成的,它将不会被解释,因为Redux-saga没有能力在其解释器中运行回调。他们只会像普通回调一样运行,而且什么都不会发生。

如果subscription.bind应该返回单个结果,则可以将该调用包装为一个返回承诺的函数,然后生成该承诺。

如果subscription.bind应该返回一串结果,您可能需要而不是创建一个channel。我想在将来有人会推出一些可以轻松地将观测数据转换为Redux传奇数据流的东西

请注意,如果您不需要多次取消订阅/重订订阅,则可能会更简单地将此代码外面的传奇,只是做

 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)); 
      } 
     }); 
+0

**这是我需要知道的。我会找出一个解决方案,并用解决方案更新我的答案。非常感谢! – janhartmann

+0

你能提供一个简单的例子:“如果subscription.bind应该返回一个单一的结果,你可以将该调用包装为一个返回承诺的函数,然后产生承诺”? – janhartmann

+0

用我的解决方案更新了我的问题,您认为这足够好吗? – janhartmann