【问题标题】:Call yield put() inside a success callback在成功回调中调用 yield put()
【发布时间】:2016-08-01 21:41:19
【问题描述】:

我是 React 和 Redux 的新手。

我正在使用 react-redux 调用 AWS Cognito 服务,该服务接受一个包含成功和失败回调的对象。当我在成功回调中使用 console.log 时,我从 AWS Cognito 取回了我的 JWT;但是,我怎么能在这个回调中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){}
  });
}

【问题讨论】:

  • 为什么要使用生成器函数?如果你每次调用getAWSToken,cognito 都会给你一个新的令牌,那么生成器会改善事情吗?
  • 如前所述,我是 React 和 Redux 的超级新手,所以我正在关注示例。似乎无论在哪里使用 redux-saga,都会使用生成器函数。如果不是这种情况,请告知。
  • 嗯,这对我来说似乎过于复杂。您可以只使用普通函数,将回调传递给getAWSToken(yourCallback),然后在onSuccess 中调用该函数,如callback(result)。但是,如果有一些 redux-saga 特定的原因使用生成器函数,那么我不想建议破坏 redux-saga 的东西。
  • 你为什么说你不能在你的回调中使用yield?你有什么错误吗?因为回调不是生成器,但你的getAWSToken 是,所以你不应该对这里的yield 有任何问题。

标签: reactjs redux yield amazon-cognito redux-saga


【解决方案1】:

如果您使用的是 redux-saga(非常棒),您可以使用 call effect 将 cognitoUser.authenticateUser 之类的 asyc 回调转换为一组由中间位置执行的指令。

当中间件解析调用时,它将通过生成器单步执行下一个 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());
}

还有this incredible tutorial我强烈推荐。

编辑:为简洁起见,您省略了一些代码,但我强烈建议您将代码封装在 try catch 中的生成器中,因为您依赖于来自 API 的外部 IO。

【讨论】:

  • 感谢您的示例和教程链接,我已经了解了更多关于 call/put 的信息,然后我事先就知道了;但是,我仍然对您提供的示例有一个小问题。当我使用 cognitoUser.authenticateUser 的调用时,AWS cognito JS 库会抱怨 TypeError: Cannot read property 'getUserPoolId' of undefined,这让我认为我没有将参数正确地传递给 call() 方法。
  • 想通了,我需要传入上下文,即 cognitoUser。所以,我的电话看起来像这样。 const token = yield call([cognitoUser, cognitoUser.authenticateUser], authenticationDetails);
  • 啊!对不起,我错过了!我会为未来的观众更新答案。谢谢帕特里克!
  • 还有一件事。此 AWS 调用想要访问 authenticationDetails 的上下文(作为参数传递)。我也可以传递那个上下文吗?顺便说一句,您可以使用apply(context, fn, args) 而不是call([context, fn], args)
  • authenticationDetails 本身就是一个上下文(上下文就是一个对象)。您必须在 API 调用中单独传递它们,因为调用将方法调用的定义构建到一个函数中,而无需了解实例本身。它会给你一个有用的错误吗?
猜你喜欢
  • 2017-06-14
  • 2017-08-19
  • 2018-07-08
  • 1970-01-01
  • 1970-01-01
  • 2020-07-23
  • 1970-01-01
  • 2023-03-19
  • 2015-01-10
相关资源
最近更新 更多