【问题标题】:Firebase Promises Issue - "Maximum call stack size exceeded"Firebase Promises 问题 - “超出最大调用堆栈大小”
【发布时间】:2019-02-14 08:14:44
【问题描述】:

我遇到了Callable Functions 的问题。这是我的 Firebase 函数:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request-promise');

admin.initializeApp(functions.config().firebase);

exports.phoneAuthRequest = functions.https.onCall((data, context) => {
  // Message text passed from the client.
  const text = data.text;

  // Authentication / user information is automatically added to the request.
  const uid = context.auth.uid;
  const phone = context.auth.token.phone_number;

  const url = "https://api.authy.com/protected/json/phones/verification/start?api_key=<key here>&via=sms&country_code=1&phone_number=" + phone;
  const httpReq = {
    uri: url,
    method: 'POST',
    json: true,
    resolveWithFullResponse: true
  };

  return new Promise((resolve, reject) => {
    request(httpReq).then((response) => {
      // Twillio request returned with success
      console.log("response: " + JSON.stringify(response));
      return resolve(response);
    }).catch(function(error) {
      console.log("error: " + JSON.stringify(error));
      return reject(error);
    });  
  });
});

这是我的客户示例:

<html>
  <head>
    <script src="https://www.gstatic.com/firebasejs/5.4.2/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/5.4.2/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/5.4.2/firebase-database.js"></script>
    <script src="https://www.gstatic.com/firebasejs/5.4.2/firebase-functions.js"></script>

    <script>
      var config = { <firebase configuration in here> };
      firebase.initializeApp(config);

      function myTest() {
        var display = document.getElementById('display');
        display.innerHTML = "Started";

        var auth = firebase.auth();
        auth.signInWithEmailAndPassword(<username>,<password>).then(function(authResult) {
          display.innerHTML = "Signed in";

          var phoneAuthRequest = firebase.functions().httpsCallable('phoneAuthRequest');
          phoneAuthRequest({'text': 'Test'}).then(function(result) {
            display.innerHTML = JSON.stringify(result);
          }).catch(function(error) {
            display.innerHTML = JSON.stringify(error);
          });
        }).catch(function(error) {
          display.innerHTML = "Login failure.  Your email or password could not be validated.  " + JSON.stringify(error);
        });
      }
    </script>
  </head>

  <body>
    <input type="submit" value="Test It" data-wait="Loading..." id="loginBtn" class="login-window-login-btn w-button" onclick="myTest();">
    <div id="display"></div>
  </body>
</html>

对此代码组合的测试表明,Firebase 函数“phoneAuthRequest”被调用,进而向 Twillio 发出请求,并且 Twillio 的响应在响应中正确返回,但控制台日志显示此错误:

Unhandled error RangeError: Maximum call stack size exceeded
    at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13395:23)
    at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15
    at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)
    at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)
    at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15
    at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)
    at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)
    at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15
    at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)
    at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)
    at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38
    at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15
    at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)
    at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)
    at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)

当然,客户端的响应是:

{"code":"internal"}

当我阅读类似的帖子时,建议是序列化承诺,我不确定我是否完全理解如何做,或者包装异步调用(在这种情况下是请求)在一个新的承诺中,这正是我在这里所做的,它仍然不起作用。

如果您要回答这个问题,您能否通过显示代码示例具体说明建议的解决方案?

提前谢谢...

【问题讨论】:

  • 是否有更多关于该错误的信息?错误通常包括某种关于错误发生位置的跟踪 - console.log 输出错误?
  • 我已更新主线程以包含完整错误。毫无疑问,promise 函数以某种方式循环,可能是由于编码错误。我只需要了解我做错了什么,以及如何解决它。
  • 是客户端还是服务器端的错误?
  • 服务器上的错误。
  • response: 是否已登录?

标签: javascript function firebase google-cloud-functions callable


【解决方案1】:

尝试去掉客户端,通过curl调用Firebase函数。

Call functions via HTTP requests

【讨论】:

【解决方案2】:

好的,我用大量的头撞墙解决了这个问题。代码如下:

exports.phoneAuthRequest = functions.https.onCall((data, context) => {
  // Example of using context to obtain the user information about the calling user
  const uid = context.auth.uid;
  // Example of obtaining a paramter that was passed by the calling function
  const phone = data.phone;
  const e164 = "+1" + phone;

  httpReq = ...

  // Example of a return if you have not yet made a call to an asynchonous function.
  return ({'status': 'success'});

  // Here is an example of a nested set of asynchonous calls and how to return from them.
  return admin.auth().updateUser(uid, {'phoneNumber': e164}).then(function(userRecord) {
    // the Phone Number was updated
    return request(httpReq).then((response) => {
      var updates = {};
      updates['/users/' + uid + "/centralVerified"] = false;
      return database.ref().update(updates).then(function(rslt) {
        return Promise.resolve({'status': 'success');
      }).catch(function(error) {
        return Promise.reject({'status': 'failed'});
      });
    }).catch(function(error) {
      return Promise.reject({'status': 'failed'});
    });
  }).catch(function(error) {
    return Promise.reject({'status': 'failed'});
  });
});

请注意,上面有两种从可调用函数返回的不同方式。如果您没有进行任何异步调用,那么您可以简单地返回值,但如果您调用了异步函数,则必须返回一个 Promise。如果您在调用例程中查找 Reject 或 Resolve,则假定返回值是 Resolve。

我希望这对其他人有所帮助...祝你好运!

【讨论】:

    猜你喜欢
    • 2018-06-03
    • 2019-02-01
    • 1970-01-01
    • 2015-10-24
    • 2015-12-29
    • 2017-12-27
    • 2020-12-06
    • 2020-11-16
    • 2019-05-04
    相关资源
    最近更新 更多