Вызов yield put() внутри успешного обратного вызова

Я новичок в React и Redux.

Я использую react-redux для вызова службы AWS Cognito, которая принимает объект, содержащий обратный вызов успеха и неудачи. Я получаю свой JWT от AWS Cognito, когда я console.log внутри своего обратного вызова успеха; однако как я могу yield put() внутри этого обратного вызова, так как это не функция генератора (function*).

Вот код:

export function* getAWSToken(){
  // username, password and userPool come from react state
  // not showing code for brevity.

  const userData = {
      Username: username,
      Pool: userPool,
    };
  const authenticationData = {
    Username : username,
    Password : password,
  };

  const cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
  const authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);

  // This here is the callback
  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess(result){
      yield put(cognitoTokenObtained(result.getIdToken().getJwtToken())
    },
    onFailure(err){}
  });
}

person Community    schedule 01.08.2016    source источник
comment
Зачем использовать функцию генератора? Если каждый раз, когда вы вызываете getAWSToken, cognito выдает вам новый токен, улучшит ли ситуацию генератор?   -  person David Gilbertson    schedule 02.08.2016
comment
Как было сказано выше, я новичок в React и Redux, поэтому привожу примеры. Похоже, что везде, где используется redux-saga, используется функция генератора. Если это не так, пожалуйста, сообщите.   -  person    schedule 02.08.2016
comment
Хм, мне это кажется слишком сложным. Вы можете просто использовать обычную функцию, передать обратный вызов getAWSToken(yourCallback), а затем вызвать эту функцию внутри onSuccess, например callback(result). Но если есть какая-то специфическая для redux-saga причина для использования функций генератора, то я бы не хотел предлагать что-то, что нарушает redux-saga.   -  person David Gilbertson    schedule 02.08.2016
comment
Почему вы говорите, что не можете использовать yield в обратном вызове? У тебя есть ошибка? Поскольку обратный вызов не является генератором, а ваш getAWSToken, поэтому у вас не должно быть проблем с yield здесь.   -  person Pierre Criulanscy    schedule 02.08.2016


Ответы (1)


Если вы используете redux-saga (что замечательно), вы можете использовать эффект вызова для преобразования обратного вызова asyc, такого как cognitoUser.authenticateUser, в набор инструкций, которые должны быть выполнены посередине.

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

export function* getAWSToken(){
  // username, password and userPool come from react state
  // not showing code for brevity.

  const userData = {
      Username: username,
      Pool: userPool,
    };
  const authenticationData = {
    Username : username,
    Password : password,
  };

  const cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
  const authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);

  // Note: since you're invoking an object method
  // you'll want to pass the object's context (this) with the call via an array

  const token = yield apply(cognitoUser, cognitoUser.authenticateUser, [authenticationDetails, { onSuccess(response){return response}, onFailure(){} }]);

  yield put(cognitoTokenObtained(token.getIdToken().getJwtToken());
}

Есть также это невероятное руководство, которое я очень рекомендую.

Редактировать: вы пропустили некоторый код для краткости, но я настоятельно рекомендую обернуть код внутри генератора в try catch, поскольку вы зависите от внешнего ввода-вывода из API.

person The Brofessor    schedule 02.08.2016
comment
Спасибо за ваш пример и ссылку на учебник, я узнал больше о call/put, чем знал заранее; однако у меня все еще есть небольшая проблема с приведенным вами примером. Когда я использую вызов для cognitoUser.authenticateUser, библиотека AWS cognito JS жалуется на TypeError: Cannot read property 'getUserPoolId' of undefined, что заставляет меня думать, что я неправильно передаю параметры в метод call(). - person ; 02.08.2016
comment
Разобрался, мне нужно было передать контекст, то есть cognitoUser. Итак, мой звонок выглядит так. const token = yield call([cognitoUser, cognitoUser.authenticateUser], authenticationDetails); - person ; 02.08.2016
comment
Ах! Извините, я пропустил это! Я обновлю ответ для будущих зрителей. Спасибо, Патрик! - person The Brofessor; 02.08.2016
comment
Еще кое-что. Этот вызов AWS запрашивает доступ к контексту authenticationDetails (который передается как параметры). Могу ли я передать этот контекст? Кстати, вы можете использовать apply(context, fn, args) вместо call([context, fn], args) - person ; 03.08.2016
comment
authenticationDetails сам по себе является контекстом (контекст — это объект). Вы должны передавать их отдельно в вызове API, потому что вызов строит определение вызова метода в функцию без знания самого экземпляра. Это вообще дает вам полезную ошибку? - person The Brofessor; 03.08.2016
comment
При вызове с применением, а не вызовом, который принимает первый параметр в качестве контекста, я заработал; однако код не уступает. Я console.log сразу после const token и получаю undefined, затем срабатывает console.log, который я вставил в обратный вызов onSuccess. - person ; 03.08.2016
comment
обратный вызов onSuccess, который вы передаете в качестве аргумента, ничего не возвращает, что, если вы попробуете сделать выше? Я просто отредактировал это, если это действительно похоже - person The Brofessor; 03.08.2016
comment
Давайте продолжим это обсуждение в чате. - person ; 03.08.2016
comment
Учебник был перемещен в redux-saga.github.io/ редукс-сага/документы/введение/ - person Chebyr; 04.01.2017