2017-02-21 5 views
2

Есть ли примеры использования redux-loop для обработки сложных рабочих процессов ajax? Официальное репо очень минималистично. Из одного примера в дикой природе я смог найти (https://hackernoon.com/why-i-wrote-a-redux-async-outerware-277d450dba74#.2ocaloc58), кажется, что loop-loop очень похож на redux-thunk.Сложные примеры редукционной петли?

Вот некоторые примеры сложных рабочих процессов АЯКС:

  • Ajax Workflow1. Пользователь выбирает два разных фильтра в таблице результатов. Каждый фильтр инициирует запрос ajax, который затем отменяет порядок. В таблице результатов должен отображаться правильный выбор фильтра. Ошибки не должны обновлять таблицу результатов.
  • Ajax Процедура 2
    • Пользователь запускает генерацию отчета (который представляет собой длинный ход процесса).
    • Пользователь переключается на другой отчет. Он должен либо отменить, либо проигнорировать ожидающее действие «ждать отчета».
  • Более сложный технологический процесс (основанный на старом примере перевождь-саг) Прессы
    • пользователя войти в кнопку, которая запускает AJAX запрос, чтобы получить авторизацию маркера
    • Либо
      • Пользователь немедленно нажимает кнопку выхода из системы, которая должна отменить/игнорировать ожидающее действие auth
      • ИЛИ он должен хранить токен аутентификации при его разрешении
    • Если удалить маркер аутентификации после выхода из системы или если происходит ошибка входа в систему

ответ

2

Я дам шанс на второй рабочий процесс (логин).

Прежде чем перейти к коду, стоит отметить, что redux-loop намного проще и предлагает менее redux-saga с точки зрения потока асинхронного управления. Но в духе Elm основное внимание уделяется потоку данных - неудивительно, что обычно это достигается с помощью типов данных. Поэтому полезно думать с точки зрения статически типизированного языка. В Haskell или Elm, вероятно, это полезно для моделирования проблемы по типу данных, который сам по себе кодирует конечный автомат:

data LoginStatus data err = 
    LoggedOut  | 
    , LoggedIn data | 
    , LoginError err | 
    , Pending 

Где data и err являются переменными типа представляют логин тип данных (жетоны) и логин ошибок. JavaScript, динамически типизированный, не имеет преимущества, выражающего ту же идею, но есть много динамических трюков, которые можно использовать для имитации тегированных типов объединения, таких как LoginStatus. Без дальнейшего назад, вот код:

import {match} from "single-key"; 

export default function reducer(state, action) { 
    return match(state, { 
    LoggedOut :() => loggedOutReducer(state, action), 
    LoggedIn :() => loggedInReducer(state, action), 
    Pending :() => pendingReducer(state, action), 
    LoginError :() => loginErrorReducer(state, action) 
    }); 
} 

Здесь я буду использовать простую и менее известную библиотеку singe-key для достижения самых основных типов времени выполнения профсоюза. Объект «с одним ключом», как его называют, представляет собой объект с одним ключом и значением, например { a: 1 } («a» - это ключ, а 1 - значение).Мы будем моделировать состояние с однокнопочными объектами - разные ключи представляют разные варианты LoginStatus. Несколько примеров гласит:

{ 
    LoggedOut : true 
} 


{ 
    LoggedIn : { 
    token : 1235, 
    user : { firstName: "John" } 
    } 
} 

{ 
    Pending : true 
} 

С этим прояснилось, вот суб-редукторы, используемые в главном редукторе:

// state :: { LoggedIn: {/* some data * } } 
function loggedInReducer(state, action) { 
    if (action.type === LOGOUT) { 
    return { 
     LoggedOut : true 
    }; 
    } 
    return state; 
} 
// state :: { Pending : true } 
function pendingReducer(state, action) { 
    if (action.type === LOGIN_SUCCESS) { 
    return { 
     LoggedIn : { 
     token : action.payload.token, 
     user : action.payload.user 
     } 
    }; 
    } 
    if (action.type === LOGIN_ERROR) { 
    return { 
     LoginError : action.payload; 
    }; 
    } 
    if (action.type === LOGOUT) { 
    return { 
     LoggedOut : true 
    }; 
    } 
    return state; 
} 
// state :: { LoggedOut : true } 
function loggedOutReducer(state, action) { 
    if (action.type === LOGIN) { 
    return loop({ Pending: true }, Effects.promise(loginRequest)); 
    } 
    return state; 
} 
// state :: { LoginError : error } 
function loginErrorReducer(state, action) { 
    if (action.type === LOGIN) { 
    return loop({ Pending: true }, Effects.promise(loginRequest)); 
    } 
    return { LoggedOut : true }; 
} 

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

return loop({ Pending: true }, Effects.promise(loginRequest)); 

Это состояние переходов от LoggedOut/LoginError в Pending и указать некоторые побочные эффекты - которые будут запланированы на redux-loop. Вы можете даже объединить два варианта в один: { LoggedOut : error | null }, но я чувствую, что состояние в отдельности LoginError полезно в долгосрочной перспективе.

С некоторым представлением типов данных эту проблему легче осмыслить, чем она появляется впервые; вы можете сделать то же самое с редуктором, структурированным примерно одинаково, и использовать только redux-thunk.

+0

Я ценю ответ, но ... проблема с этим подходом заключается в том, что он смешивает обязанности. Асинхронный рабочий процесс + «нормальное» состояние. Это приводит к сложным редукторам. В реальных проектах это означает, что вы просто упростили создание хрупкого кода. Кроме того, вы не рассмотрели, как на самом деле выполнять описанные выше рабочие процессы. –

+0

Спасибо за отзыв. Это разумная критика. В последнем пункте, я считаю, я в основном рассмотрел, как это будет работать. Хорошо, так как сегодня у меня есть свободное время, просто сделал рабочий пример, используя объяснительную схему редуктора, описанную здесь. У него есть реализация «redux-loop» и «redux-sage» с почти идентичными редукторами: [https://github.com/yiransheng/redux-login-examples](https://github.com/yiransheng/redux -login-examples) –

+0

Что хорошего в вашей идее явного перечисления типов. К сожалению, как говорится в Америке: «Ты избиваешь мертвую лошадь». Кроме того, для смешивания проблем у вас нет специального API для обработки асинхронности. Следовательно, в реальных проектах код становится очень, очень сложным (и повторяющимся). Например, вы не обрабатываете случай отмены. Во-вторых, FRP/sagas выигрывают в тестировании. Вам не нужны издевки. –

Смежные вопросы