【问题标题】:Firebase functions 'Converting circular structure to JSON at JSON.stringify'Firebase 函数“在 JSON.stringify 中将循环结构转换为 JSON”
【发布时间】:2019-12-11 11:24:14
【问题描述】:

我正在为我的应用程序制作自定义电子邮件处理程序,这是我的代码:

const express = require('express');
const firebase = require('firebase');
const functions = require('firebase-functions');


firebase.initializeApp({
  apiKey: "",                           
  authDomain: "app.firebaseapp.com",         // Auth with popup/redirect
  databaseURL: "https://app.firebaseio.com", // Realtime Database
  storageBucket: "app.appspot.com",          // Storage
  messagingSenderId: "123456789"   
});

const auth = firebase.auth()

const app = express();

app.get('/', (req, res) => {
  res.send('Website in progress...');
});

app.get('/auth/**', (request, response) => {
   // Get the action to complete.
   var mode = request.query.mode;
   // Get the one time code to authenticate.
   var actionCode = request.query.oobCode;
   // (Optional) Get the contine URL .
   var continueURL = request.query.continueURL; 
   // (Optional) Get the language code.
   var lang = request.query.lang;


   // What mode is it?
   switch (mode){
      case 'resetPassword':
        // Reset password - display UI and init backend code.
        response.send(resetPassword(actionCode, continueURL, lang));
        break;
    case 'recoverEmail':
        // Recover email - display UI and init backend code.
        //recoverEmail(auth, actionCode, lang);
        break;
    case 'verifyEmail':
        // Verify email - display UI and init backend code. 
        //verifyEmail(auth, actionCode, continueURL, lang);
        break;
    default:
        //response.send('Error')
        response.send("Internal server error - no API token.")
}
});

function resetPassword(actionCode, continueURL, lang){
   var accountEmail;

   return auth.verifyPasswordResetCode(actionCode).then(changePassword(actionCode))
}

function changePassword(actionCode){
   newPassword = 'newPassword'
   auth.confirmPasswordReset(actionCode, newPassword).then(function(resp){
      return resp;
   }).catch(function(error){
      return error
   });
}


exports.app = functions.https.onRequest(app);

当我单击密码重置电子邮件中的链接时,该链接将我带到网站 (website.com/auth/action.../),我从 firebase 上的功能日志中收到此错误,我猜是什么时候我尝试返回响应值,但它不能,因为它是 JSON 格式? :

Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at stringify (/srv/node_modules/express/lib/response.js:1123:12)
at ServerResponse.json (/srv/node_modules/express/lib/response.js:260:14)
at ServerResponse.send (/srv/node_modules/express/lib/response.js:158:21)
at app.get (/srv/index.js:37:22)
at Layer.handle [as handle_request] (/srv/node_modules/express/lib/router/layer.js:95:5)
at next (/srv/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/srv/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/srv/node_modules/express/lib/router/layer.js:95:5)
at /srv/node_modules/express/lib/router/index.js:281:22

【问题讨论】:

  • 您到底打算向客户发送什么?现在,您正在发送由 resetPassword 返回的承诺,这肯定不会按您预期的方式工作。
  • @DougStevenson 我在创建我的自定义电子邮件处理程序时遇到了问题,我刚刚解决了这个问题,只是想看看我所做的是否真的有效。我认为这是正确的做法?
  • 由于我不确切知道您要发送给客户端的内容,因此我无法告诉您此处的代码是否正确。我可以说出问题的根源,但除此之外我无能为力。您可能需要学习如何更好地处理承诺。
  • @DougStevenson 老实说,我刚刚在学校,午餐快结束了,我赶紧赶过去看看是否有任何回复。 Samthecodingman 在下面的回答帮助我很好地解决了这个问题,感谢 Doug 的帮助!

标签: firebase firebase-authentication google-cloud-functions


【解决方案1】:

除了圆形物体的问题,大概和这行有关:

response.send(resetPassword(actionCode, continueURL, lang));

您的 resetPassword 函数返回一个 Promise,不应将其传递给 response.send(...)。相反,您应该通过链接发送 Promise 的结果。

resetPassword(actionCode, continueURL, lang)
  .then((result) => response.send(result));
  .catch((error) => { // don't forget to handle errors
    console.log("ERROR:", error);
    response.sendStatus(500)
  });

你也应该改变

return auth.verifyPasswordResetCode(actionCode).then(changePassword(actionCode));

return auth.verifyPasswordResetCode(actionCode).then(() => changePassword(actionCode));

否则,then() 将尝试错误地调用 changePassword(actionCode) 的结果,就像它是一个函数一样。

【讨论】:

  • 哦,太好了!非常感谢你,我不知道。
  • @samethecodingman 对此我感激不尽,我已经在这里待了好几天想弄清楚这一点,我想我只是需要休息一下啊哈哈。成功了!
【解决方案2】:

TL;DR在发送响应之前序列化循环引用

Converting circular structure to JSON 实际上是 JS 中非常常见的类型错误,并不局限于 Firebase。根据MDN docs

JSON 格式本身不支持对象引用(尽管IETF draft exists),因此JSON.stringify() 不会尝试解决它们并相应地失败。

不过,您可以通过多种方式尝试字符串化。例如,MDN 提供了一个示例,您可以使用该示例解决此问题

const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return;
      }
      seen.add(value);
    }
    return value;
  };
};

JSON.stringify(circularReference, getCircularReplacer());

上面的 sn-p 是我推荐的路线,但如果您想要更方便的东西方便存在一个 npm 包 (circular-structure-stringify),它以类似的方式序列化循环引用。请注意,我已经超过 6 个月没有维护这个包了,但是,它仍然可以作为您的问题的可能解决方案。

【讨论】:

  • @JKLleinne 谢谢你的回答,我会试试的。出于兴趣,我的代码的哪一部分导致了该错误?
  • 别担心,我建议序列化 response.send 中传递的内容以开始
猜你喜欢
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 2017-04-03
  • 2020-05-31
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多