【问题标题】:Firebase Functions returns and promises do not exit the functionFirebase 函数返回和承诺不退出函数
【发布时间】:2018-04-29 21:07:51
【问题描述】:

我仍然是 Firebase 领域的初学者,我一直试图找出以下代码的问题,但我以各种可能的方式失败了。

代码应该从数据库中的用户配置文件中检索uid,然后使用它来更新身份验证配置文件,如果身份验证配置文件更新成功,则再次更新数据库配置文件。

index.js 中,我定义了一个导出函数来处理来自HTML 表单的POST 参数。下面的代码在另一个模块文件中定义了处理函数:

 exports.auUpdateUserByEmail = (req, res) => {
  // This handler function will retrieve the POSTed params of user profile
  // and will attempt to update the existing user authentication as well as
  // the database profiles.
  //
  // This function accepts the following params:
  // 1. User email   // 2. Phone number   // 3. password   // 4. Display name
  // 5. Photo url   // 6. Disabled Flag
  //

  var db = admin.firestore();

  var uEmail = req.body.userEmail;
  var dName = req.body.displayName;
  var userId = "";

  var newuser = {
    displayName: dName
  }

  console.log("Email passed: " + uEmail);

  // Fetch the user UID by user email...
  res.write('User UID: ' + userId);
  console.log('User UID: ' + userId);

  // attempt to update the user authentication profile...
  return db.collection('Users').where('email', '==', email).get()
  .then(snapshot => {
    snapshot.forEach(doc => {
        var d = doc.data();
        console.log("doc.id: " + doc.id + " - d.email: " + d.email);
        if(d.email == email)
        {
          userId = d.uid;
        }
    });

    return admin.auth().updateUser(userId, newuser);
  }).then(function(userRecord) {
    // The updating was successful... Attempt to update User Details in
    // database User Profile...
    console.log("User Updated Successfully. UID: " + userRecord.uid);
    retUid = userRecord.uid;

    // Create a reference to the Users Database...
    var docRef = db.collection('Users');

    // Update the user profile document.
    return docRef.doc(userRecord.uid).update(newuser);
  }).then(result => {
    // everything went fine... return User UID as a successful result...
    res.write(userId);

    return res.end();

  }).catch(function(error) {
    console.log("doc.update - Error updating user profile in database:", error);
    return res.end();

  });
}

index.js 中,我有以下导出定义:

var appAuth = express();
//Here we are configuring express to use body-parser as middle-ware.
appAuth.use(bodyParser.urlencoded({ extended: false }));
appAuth.use(bodyParser.json());

appAuth.post('/updateUserByEmail', authusers.auUpdateUserByEmail);

exports.usersAuthFunctions = functions.https.onRequest(appAuth);

我不得不说我得到了uid,更新了身份验证配置文件,然后更新了数据库配置文件,但它一直在等待函数返回。

感谢您的宝贵帮助。谢谢。


我已经更新了如下代码,它完成了工作,但是在承诺完成之前 HTTPS 退出时返回一个空白页,这会触发 "Error: write after end" 错误。

var fetch_uid = db.collection('Users').where('email', '==', uEmail).get()
  .then(snapshot => {
    // var userId = snapshot.data.uid;

    snapshot.forEach(doc => {
        var d = doc.data();
        console.log("doc.id: " + doc.id + " - d.email: " + d.email);
        if(d.email == uEmail)
        {
          userId = d.uid;

          res.write('User UID: ' + userId);
          console.log('User UID: ' + userId);

        }
    });

    return admin.auth().updateUser(userId, newuser);
  }).then(function(userRecord) {
    // The updating was successful... Attempt to update User Details in
    // database User Profile...
    console.log("User Updated Successfully. UID: " + userRecord.uid);
    retUid = userRecord.uid;

    // Create a reference to the Users Database...
    var docRef = db.collection('Users');

    // Update the user profile document.
    return docRef.doc(userRecord.uid).update(newuser);
  }).then(result => {
    // everything went fine... return User UID as a successful result...
    res.write(userId);

    return;

  }).catch(function(error) {
    console.log("doc.update - Error updating user profile in database:", error);
    return;

  });

  res.end();

【问题讨论】:

标签: javascript node.js firebase firebase-realtime-database google-cloud-functions


【解决方案1】:

我之前在Cloud Functions for Firebase HTTP timeout 上的回答可能对这里有帮助:

由 HTTP 请求触发的云函数需要被终止 以send()redirect()end() 结尾,否则它们 将继续运行并达到超时。

从您的代码示例中,您的 then(){} 承诺返回似乎以 res.end() 结尾,但整个函数从以下位置返回 Promise

return db.collection('Users').where('email', '==', email).get()

这可能会阻止它在你想要的时候结束。使用 HTTPS 触发器,您无需返回 Promise 来保持函数运行,只需返回结果即可。

尝试从该行删除 return 语句:

db.collection('Users').where('email', '==', email).get()

那么您只需要确保所有出口路线(或终止点)以res.end() 或类似名称结尾,因此目前您有 2 个终止点:

  }).then(result => {
    // everything went fine... return User UID as a successful result...
    res.write(userId);

    res.status(200).end();
  }).catch(function(error) {
    console.log("doc.update - Error updating user profile in database:", error);

    res.status(500).end();
  });

【讨论】:

  • 我设法让它完成工作并退出函数,但它似乎比它应该更早地退出函数,而承诺仍然悬而未决,这导致了 res.写到射击和错误!
  • 啊,我可能对编辑过于热心了,您可能只需要从db.collection('Users')[...] 行中删除return
  • 是的,但仍然......我需要它来写一些东西......返回的页面是空白的,我得到“错误:结束后写”,因为该函数存在于数据库的承诺之前.collection...get() 返回!如何让它等到这些承诺完成后才存在 http 函数?
  • 哦,抱歉,我最初的想法是错误的,请参阅我编辑的答案。您需要从the promise which will run synchronously 中删除return,然后仅在最终终止/退出点的承诺中使用end()
  • 你仍然可以使用最终的then(),但它需要以res.end() 结尾,catch() 也是如此,是的,你想要@ 987654341@在函数底部。
猜你喜欢
  • 2019-12-17
  • 2020-10-11
  • 2020-07-17
  • 2017-04-05
  • 2020-05-23
  • 2022-01-26
  • 2019-05-25
  • 2014-07-05
相关资源
最近更新 更多