2016-05-01 4 views
1

Сейчас я пытаюсь получить начальное состояние моей стороне сервера приложений через повторный набор номера.Использование Redux-сагу и повторного набора серверную

Повторный набор запускает действие чистого объекта, а redux-saga прослушивает/ожидает этого действия, а затем запускает запрос async.

Но проблема заключается в том, что Redial не имеет никаких обещаний решить, когда завершающая сага завершена, потому что она отправляет чистый объект.

Компонент

const redial = { 
    fetch: ({ dispatch }) => dispatch({ type: actionTypes.FETCH_START }), 
}; 

export default class PostList extends Component { 
    render() { 
     const { posts } = this.props; 
     return (
      <div> 
       {posts.map(post => <ListItem key={post.id} post={post} />)} 
      </div> 
     ); 
    } 
} 

PostList.propTypes = { 
    posts: PropTypes.array.isRequired, 
}; 

export default provideHooks(redial)(connect(mapStateToProps)(PostList)); 

Saga

export function *fetch() { 
    try { 
     yield put({ type: actionTypes.FETCH_START }); 
     const response = yield call(fakeData); 
     yield put({ type: actionTypes.FETCH_SUCCESS, data: response.data }); 
     yield put({ type: actionTypes.FETCH_PENDING }); 
    } catch (e) { 
     yield put({ type: actionTypes.FETCH_FAIL }); 
    } 
} 

export default function *loadPost() { 
    yield * takeLatest(actionTypes.FETCH_START, fetch); 
} 

export default function *rootSaga() { 
    yield [ 
     fork(loadPost), 
    ]; 
} 

Есть ли способ подключения redial к redux-saga?

ответ

1

Я думаю, что это может быть сделано таким образом:

во-первых, вам нужно добавить магазин в местных жителей. (Коды взяты из повторного набора README)

const locals = { 
    path: renderProps.location.pathname, 
    query: renderProps.location.query, 
    params: renderProps.params, 

    // Allow lifecycle hooks to dispatch Redux actions: 
    dispatch, 
    store 
}; 

Затем вы можете создать обещание вручную, как это:

const redial = { 
    fetch: ({ store, dispatch }) => { 
     return new Promise((resolve, reject) => { 
      const unsubscribe = store.subscribe(()=>{ 
       if (store.getState()...) { // monitor store state changing by your saga 
        resolve(...) //you probably dont need any result since your container can read them from store directly 
        unsubscribe(); 
       } 
       if (store.getState()....error) { 
        reject(...) 
        unsubscribe(); 
       } 
      }); 
      dispatch({ type: actionTypes.FETCH_START }), 
     } 
    } 
}; 

Эти коды предназначены только для демонстрации, не использовать их в производстве без надлежащего тестирования.

Я думаю, что может быть более элегантный способ отслеживания результатов выполнения саги, чем проверка состояния хранилища регрессирования снова и снова, пока состояние не соответствует этим if (...) утверждениям, возможно, вы можете запустить сагу с магазином редукта и внешними слушателями , то эти перехватчики не обязательно будут знать о вашей структуре магазина.

0

Существует довольно элегантный способ сделать это. Прежде всего, вам нужно создать реестр для ваших задач саг (помните, что запуск .run метод промежуточного программного обеспечения возвращает дескриптор задачи):

export default class SagaTaskRegistry { 
    constructor() { 
    this._taskPromises = []; 
    } 

    addTask(task) { 
    if (!this._taskPromises) { 
     this._taskPromises = []; 
    } 
    this._taskPromises.push(task.done); 
    } 

    getPromise() { 
    return new Promise((resolve) => { 
     const promises = this._taskPromises; 
     if (!promises) { 
     resolve(); 
     return; 
     } 
     this._taskPromises = undefined; 
     Promise.all(promises).then(resolve).catch(resolve); 
    }).then(() => { 
     const promises = this._taskPromises; 
     if (promises) { 
     return this.getPromise(); 
     } 
     return undefined; 
    }); 
    } 
} 

При добавлении новых задач в саге промежуточного слоя с помощью .run, вы тогда звоните registryInstance.add(taskDescriptor). SagaTaskRegistry возьмет обещание для этой задачи и добавит его в массив.

Позвонив по номеру getPromise, вы получите обещание, которое будет разрешено, когда все добавленные задачи будут завершены. Он никогда не будет отклонен, так как вы, скорее всего, не захотите, чтобы неудачные выборки приводили к отказу - вы все равно хотите отобразить свое приложение с состоянием ошибки.

И это, как вы можете комбинировать его с redial:

import createSagaMiddleware from 'redux-saga'; 
import { applyMiddleware, createStore } from 'redux'; 
import rootReducer from 'your/root/reducer'; 
import yourSaga from 'your/saga'; 

const sagaMiddleware = createSagaMiddleware(); 
const middleWare = [sagaMiddleware]; 
const createStoreWithMiddleware = applyMiddleware(...middleWare)(createStore); 
const store = createStoreWithMiddleware(rootReducer); 
const sagaTaskRegistry = new SagaTaskRegistry(); 
const sagaTask = sagaMiddleware.run(yourSaga); 
sagaTaskRegistry.addTask(sagaTask); 

match({ routes, history }, (error, redirectLocation, renderProps) => { 
    const locals = { 
    path: renderProps.location.pathname, 
    query: renderProps.location.query, 
    params: renderProps.params, 
    dispatch: store.dispatch, 
    }; 

    trigger('fetch', components, locals); 

    // Dispatching `END` will force watcher-sagas to terminate, 
    // which is required for the task promises to resolve. 
    // Without this the server would never render anything. 
    // import this from the `redux-saga` package 
    store.dispatch(END); 

    // The `SagaTaskRegistry` keeps track of the promises we have to resolve 
    // before we can render 
    sagaTaskRegistry.getPromise().then(...) 
}); 

компонент теперь может быть украшен простым крючком:

const hooks = { 
    fetch: ({ dispatch }) => { 
    dispatch(yourAction()); 
    }, 
}; 

С этого вы можете просто использовать саги как обычный. Это должно дать вам возможность делать то, что вы пытаетесь. Вы можете дополнительно отвлечь его, чтобы обеспечить динамическую регистрацию саг через фрагменты кода и другие вещи. Реестр задач уже работает для этих случаев использования, проверяя новые зарегистрированные задачи со времени последнего звонка до getPromise, прежде чем фактически выполнить обещание.