首页 > 解决方案 > 带有数据库承诺的javascript递归函数

问题描述

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

我的数据库中有一个用户表。任何用户都可以是会员,任何会员都可以有 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) => {
    });
});

递归函数符合我的预期——我得到了一个引用成员 ID 的列表,但显然我必须以某种方式处理异步性质,这就是我被卡住的地方。我以为我可以通过递归构建一组承诺,然后在返回原始调用时解决这些承诺(可能有一个全局承诺数组),但这似乎不起作用。我还尝试将单个 member_id 传递给递归函数并在 DB 调用后继续循环,所以我只处理一次事件,但这也不起作用。

任何指导将不胜感激!

标签: javascriptdatabaserecursionpromiseknex.js

解决方案


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});
)

推荐阅读