2016-06-09 26 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