为什么我的嵌套承诺会返回未定义的内容?

时间:2020-06-11 15:39:22

标签: javascript async-await

这是我的代码:

resolve: async (
        _root,
        { data: { password, interests, email, ...userData } },
        { prisma }
      ) => {
        console.log('called reg');
        const handleError = (error) => {
          console.log('error: ', error);
          return { token: null, error, userId: null };
        };
        return admin
          .auth()
          .createUser({
            email,
            password,
            displayName: `${userData.firstName} ${userData.lastName}`,
          })
          .then((userRecord) => {
            // See the UserRecord reference doc for the contents of userRecord.
            console.log('Successfully created new user:', userRecord);
            return admin
              .database()
              .ref('users/' + userRecord.uid)
              .set(
                {
                  ...userData,
                  interests,
                },
                (error) => {
                  if (error) return handleError(error);
                  else {
                    return admin
                      .auth()
                      .createCustomToken(userRecord.uid)
                      .then((token) => {
                        console.log('token: ', token)
                        return {
                          token,
                          error: null,
                          userId: userRecord.uid,
                        };
                      }, handleError);
                  }
                }
              );
          }, handleError)
          .then((result) => {
            console.log('result: ', result);
            return result;
          });
      },

我在我的graphql解析器中使用了嵌套,那么我的问题是,为什么最后一个结果然后返回未定义?我无法弄清楚,因为当我登录createCustomToken的回调时,令牌就在那儿,因此我确保最后要记录结果,但是不幸的是,它是未定义的,基本上,我想使用.then并像这样捕获,不是asyc / await,有帮助吗?

1 个答案:

答案 0 :(得分:0)

您不应在set方法中使用回调,而应将then链接到该方法。使用回调时,set方法将返回undefined,然后在最后一个result块中将其分配给thenFirebase Docs

此外,您不必在每个handleError方法中都提供相同的then参数。您可以通过在末尾链接catch方法来替换它们。

...
return admin
  .database()
  .ref("users/" + userRecord.uid)
  .set({
    ...userData,
    interests,
  })
  .then(() => admin.auth().createCustomToken(userRecord.uid))
  .then((token) => {
    console.log("token: ", token);
    return {
      token,
      error: null,
      userId: userRecord.uid,
    };
  })
  .then((result) => {
    console.log("result: ", result);
    return result;
  }).catch(handleError);

我认为,您的代码很难阅读。编写更具可读性的代码将使调试过程更容易,并且通常,异步/等待可以提高可读性。

async/await版本的代码:

async (
  _root,
  { data: { password, interests, email, ...userData } },
  { prisma }
) => {
  try {
    const userRecord = await admin.auth().createUser({
      email,
      password,
      displayName: `${userData.firstName} ${userData.lastName}`,
    });
    console.log("Successfully created new user:", userRecord);
    await admin
      .database()
      .ref("users/" + userRecord.uid)
      .set({
        ...userData,
        interests,
      });
    const token = await admin.auth().createCustomToken(userRecord.uid);
    console.log("token: ", token);
    return {
      token,
      error: null,
      userId: userRecord.uid,
    };
  } catch (error) {
    console.log("error: ", error);
    return { token: null, error, userId: null };
  }
};

当然,可读性是主观的。选择您和您的队友喜欢的样式。