当前位置: 首页 > 知识库问答 >
问题:

函数返回未定义的、预期的promise或值

盖嘉珍
2023-03-14

新的云功能和承诺。我尝试在不同的位置添加承诺,但仍然在日志中得到消息。第一,我不确定我应该在哪里添加承诺,第二,我是否应该什么也不回。在调用match(如果条件满足,则创建channel)之后,我不需要执行另一个函数。虽然触发onCreate会有多个用户,所以我想确保每次执行一个用户。

const functions = require('firebase-functions');
const admin = require('firebase-admin')
admin.initializeApp();

//every time user added to liveLooking node
exports.command = functions.database
        .ref('liveLooking/{uid}')
        .onCreate((snap, context) => {
    const uid = context.params.uid
    match(uid)
})
function match(uid) {
    let m1uid, m2uid
    admin.database().ref('liveChannels').transaction((data) => {
        //if no existing channels then add user to liveChannels
        if (data === null) {
            console.log(`${uid} waiting for match`)
            return { uid: uid }
        }
        else {
            m1uid = data.uid
            m2uid = uid
            if (m1uid === m2uid) {
                console.log(`$m1uid} tried to match with self!`)
                //match user with liveChannel user
            } else {
                console.log(`matched ${m1uid} with ${m2uid}`)
                createChannel(m1uid, m2uid) 
                return null
            }
        }
    },
    (error, committed, snapshot) => {
        if (error) {
            throw error
        }
        else {
             return {
                committed: committed,
                snapshot: snapshot
            }
        }
    },
    false)
 }

function createChannel(uid1, uid2) {
    // Add channels for each user matched
    const channel_id = uid1+uid2
    console.log(`starting channel ${channel_id} with uid1: ${uid1}, uid2: ${uid2}`)
    const m_state1 = admin.database().ref(`liveUsers/${uid1}`).set({
        channel: channel_id
    })
    const m_state2 = admin.database().ref(`liveUsers/${uid2}`).set({
        channel: channel_id
    })
}

编辑1-我尝试将事务更改为使用await,这样它将只在事务之后更改UserLife节点。得到这两个警告。1)应在异步函数“match”的末尾返回一个值。2)在***return Arrow函数应返回一个值。如果use与self匹配,我不会尝试在LiveChannels下更改任何内容。不确定如何修复该警告。3)仍然在日志中获得函数返回未定义的、预期的承诺或值--我认为是命令函数。

async function match(uid) {
  let m1uid, m2uid;
  let createChannel = false
  try {
    const transactionResult = await admin
      .database()
      .ref("liveChannels")
      .transaction(
        (data) => {
             if (data === null) {
                 console.log(`${uid} waiting for match`)
                 return { uid: uid }
             }
             else {
                 m1uid = data.uid
                 m2uid = uid
                 if (m1uid === m2uid) {
                     console.log(`$m1uid} tried to match with self!`)
                     ***return***
                 } else {
                     console.log(`matched ${m1uid} with ${m2uid}`)
                     createChannel = true
                     return {}
                 }
             }
        },
        (error, committed, snapshot) => {
             if (error) {
                 throw error
             }
             else {
                  return {
                     committed: committed,
                     snapshot: snapshot
                 }
             }
        },
        false
      );

    if (transactionResult) {
        if (createChannel) {
            const channel_id = m1uid + m2uid
            console.log(`starting channel ${channel_id} with uid1:    ${m1uid}, uid2: ${m2uid}`)
            const m_state1 = admin.database().ref(`liveUsers/${m1uid}`).set({
                channel: channel_id
            })
            const m_state2 = admin.database().ref(`liveUsers/${m2uid}`).set({
                channel: channel_id
            })
            return Promise.all([m_state1, m_state2])
        }
    }
  } catch (err) {
    throw new Error(err);
  }
}

共有1个答案

易宣
2023-03-14

您没有正确管理云功能的生命周期。您需要等待所有异步任务(即对Firebase异步方法的调用)完成后,才能向平台指示它可以清理该函数。这应该通过返回一个Promise来完成,更准确地说,因为您链接了几个异步方法调用,所以应该通过返回promises链来完成。

但是,在您的云功能中还有一个问题,即您编写事务的方式。事务原子化地修改调用事务的位置(即引用)处的数据。

在代码中,可以在ref('live channels')上调用事务,但在事务内部,可以修改其他位置的数据:ref(`liveusers/${uid1}`)ref(`liveusers/${uid2}`)

这不是正确的方法:如果您希望将所有这些操作封装在一个事务中,则需要在包含您希望更改的所有节点/位置的数据库节点上调用事务,即LiveChannelsLiveUsers/${uid1}LiveUsers/${uid2}的公共父/祖节点。

如果我没有弄错的话,这三个节点的唯一公共父/祖节点是DB根节点。在DB根节点上调用事务可能不是一个好主意,特别是在有很多用户同时使用应用程序的情况下。您可能应该调整您的数据模型(DB结构)来避免这种情况。

还要注意,不是使用Tansaction的oncomplete回调来处理它的成功和失败,而是应该使用事务返回的Promise以便在Promise链中正确使用它(请参见第一段)。

 类似资料:
  • 问题内容: 我正在使用Firebase开发Server。 我已经在Youtube上复制了Google Developer的视频。 它工作正常,但在日志中出现错误: 返回的函数未定义,预期的承诺或价值 它说函数返回了,但是我返回了一个“ set” 我该如何解决? 我是Firebase Nodejs的初学者。 问题答案: 正如弗兰克在对您的帖子的评论中所指出的那样,产生警告的return语句就是这样的

  • 我是Node.js的新手,即使在阅读了其他stackflow用户提供的教程之后,我也在为承诺而挣扎。我已经花了整整一个晚上在这方面,我正在寻求帮助。我得到以下错误“Function return undefined,expected Promise or value”。我的代码在下面。我做错了什么?我还怀疑我必须使用await/async,因为它看起来像是我的代码在没有等待第一个get完成的情况下

  • 我正在尝试对Angular 5进行自定义验证,但我面临以下错误 如果值不符合要求,我只想向表单返回一个错误,这是我的代码: 这是我的表单所在的组件 此代码位于包含我要实现的验证的文件中: 这种验证只适用于可观察到的情况吗?或者我可以在没有promise或可观察的情况下进行验证吗?

  • 问题内容: 我正在尝试获取返回值,但始终无法定义。 我不确定如何获取任何返回值并在其他地方使用它?我需要使用此返回值来与其他函数进行验证,但是它似乎在范围之内。 这是我的代码: 问题答案: 移动以下行: 进入回调: 如果希望返回某些内容,则还需要向其添加回调,以便可以使用它的返回值。例如,如果您希望这样做: 这将无法正常工作,因为内容的最终值将被异步检索。相反,您需要这样做: 您不能异步返回数据。

  • 问题内容: 我有一个计算税金的函数。 我不明白为什么它不能停止递归。 问题答案: 在您的职能部门中: 您没有从函数或设置中返回值。当您不返回任何内容时,返回值为。 也许,您想要这样: