javascript 具有数据库承诺的递归函数

javascript recursive function with database promises

我在这上面花费了令人尴尬的时间。我可以找到几种可能的解决方案,但我似乎无法将它们映射到我的具体情况。基本问题是我对如何管理承诺缺乏了解。 非常接近并且可能是我可以使用的解决方案,但我有一个变体使其无法根据需要直接工作。

我的数据库中有一个用户 table。任何用户都可以是会员,任何会员都可以有 0 到 n 个推荐人。任何这些推荐也可以推荐成员。鉴于附属公司的 member_id,我需要获得他们所有推荐人的列表以及他们所有的推荐人、推荐人......等等,所以这是一个基本的递归问题。挑战是...我似乎无法正确完成承诺交易。

通过 api 调用完成的事情:

app.get('/api/calculateReferralTotals', (req, res) => {
    const member_id = req.body.member_id;
    knex.select('member_id').from('users').where({referred_by: 
    member_id}).then((referrals) => {
        GetReferrals(referrals);
        // do something with the global_referral_array but
        // have to deal with the promises first
        res.status(200).send({final_referral_list});
    }).catch((error) => {
        console.log("Error in select " + error);
    });
});

var global_referral_array = [];
function GetReferrals(referrals) {
    referrals.forEach((amb) => {
        knex.select('member_id').from('users').where({referred_by: 
        amb.member_id}).then((ref) => {
            if(ref.length>0) {
            ref.forEach((element) => {
                global_referral_array.push(element.member_id);
            });
                GetReferrals(ref);
            }
        }).catch((error) => {
    });
});

递归函数如我所料 - 我得到了引用列表 member_id,但显然我必须以某种方式处理异步性质,这就是我遇到的问题。我以为我可以通过递归构建一个 promise 数组,然后在返回到原始调用时解决这些问题(可能有一个全局 promise 数组),但这似乎不起作用。我还尝试将单个 member_id 传递给递归函数并在 DB 调用后继续循环,所以我只处理单个事件,但这也不起作用。

任何指导将不胜感激!

如果用asyc函数就简单多了

不确定它是否有效,但我会试试这个:

async function GetReferrals(referrals) {
    if(!referrals) return [] // you need a condition to stop recursion

    let promises = referrals.map(amb =>knex.select('member_id').from('users').where({referred_by: 
        amb.member_id}))

    let res = await Promise.all(promises)

    return [...res, ...res.map(r => await GetReferrals(r)) ]
});

并在主通话中:

GetReferrals(referrals).then( result =>
        // do something with the global_referral_array but
        // have to deal with the promises first
        res.status(200).send({final_referral_list});
)

这应该有效。

function GetReferrals(member_id) {
  return knex.select('member_id').from('users').where({referred_by: 
  member_id}).then((referrals) => {
    const referralIds = referrals.map(element => element.member_id)
    return Promise.all(referralIds.map(GetReferrals)).then(referralsReferrals => {
      return referralsReferrals.reduce((final, arr) => final.concat(arr), referralIds)
    })
  })
}

app.get('/api/calculateReferralTotals', (req, res) => {
    const member_id = req.body.member_id;
    GetReferrals(member_id).then(final_referral_list => {
      // do something with the global_referral_array
      res.status(200).send({final_referral_list})
    }).catch((error) => {
      console.log("Error in select " + error);
    })
});