在成功的回调函数中调用yield put()

5

我是全新的React和Redux开发者。

我正在使用react-redux调用AWS Cognito服务,该服务需要一个包含成功和失败回调函数的对象。当我在成功回调函数内部console.log时,我从AWS Cognito获取我的JWT;但是,由于它不是生成器函数(function*),我如何在此回调函数内部使用 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);

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

为什么要使用生成器函数?如果每次调用 getAWSToken,cognito 都会给你一个新的令牌,那么使用生成器是否会改善情况? - David Gilbertson
正如前言所述,我对React和Redux非常陌生,因此我正在跟随示例。似乎在使用redux-saga的任何地方都会使用生成器函数。如果不是这种情况,请告知。 - user888750
嗯,对我来说似乎过于复杂了。你可以只使用普通函数,将回调传递给 getAWSToken(yourCallback),然后在 onSuccess 中调用该函数,如 callback(result)。但是,如果有使用生成器函数的 redux-saga 特定原因,那么我不想建议破坏 redux-saga 的东西。 - David Gilbertson
你为什么说在回调函数中不能使用 yield?你有任何错误吗?因为回调函数不是生成器,但是你的 getAWSToken 是,所以在这里使用 yield 不应该有任何问题。 - Pierre Criulanscy
1个回答

3
如果您正在使用redux-saga(非常棒),您可以使用call effect将异步回调如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的外部IO。


谢谢您提供的示例和教程链接,我对call/put有了更深入的了解。然而,我仍然在使用您提供的示例时遇到了一些问题。当我在cognitoUser.authenticateUser中使用call时,AWS cognito JS库会报错:TypeError: Cannot read property 'getUserPoolId' of undefined,这让我认为我没有正确地将参数传递给call()方法。 - user888750
搞定了,我需要传递上下文,即cognitoUser。因此,我的调用看起来像这样:const token = yield call([cognitoUser, cognitoUser.authenticateUser], authenticationDetails); - user888750
啊!抱歉我错过了那个问题!我会更新答案以便未来的观众。谢谢Patrick! - The Brofessor
还有一件事。这个 AWS 调用需要访问 authenticationDetails 的上下文(作为参数传递)。我能同时传递那个上下文吗?顺便说一句,你可以使用 apply(context, fn, args) 代替 call([context, fn], args) - user888750
你传递的 onSuccess 回调函数作为参数没有返回任何内容,如果尝试上述方法会怎样?我刚刚编辑了一下,如果看起来非常相似。 - The Brofessor
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接