Home > Software design >  async/await troubles in a recursive Redis function
async/await troubles in a recursive Redis function

Time:10-20

Ima rookie using async/await but must now to use Redis-om. NN_walkd walks through a Redis database looking for loop-chains and does this by recursion. So the 2 questions I have is:

  1. Am I calling the inner recursive NN_walkd calls correctly via async/await?
  2. At runtime, the compSearchM proc is called first and seems to work (it gets 5 entries so it has to call NN_walkd 5 times). A NN_walkd is then recursively called, and then when it loops the 1st time it then calls compSearchK where the problems are. It seems to sit on the first Redis call in compSearchK (.search). Yet the code for compSearchK and compSearchM look basically identical.

main call

NN_walk = async function(req, db, cnode, pnode, chain, cb) {
  var vegas, sneaker;

  req.session.walk = [];
  await NN_walkd(req, cnode, pnode, [], 1);
  req.session.walk = null;
  console.log('~~~~~~~~~~~~ Out of Walk ~~~~~~~~~~~~~~~');
  cb();
};

redis.mjs

export class RedisDB {
  constructor() {
    ...
    this._companyRepo = ...
  }
  compSearchK(ckey) {   // doesn't matter if I have a async or not here
    return new Promise(async (resolve) => {
      const sckey = await this._companyRepo.search()
        .where('COMPANYKEY').equals(ckey)
        .return.all();
      if (sckey.length) {
        const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
        resolve(ttrr.toJSON());
      } else
        resolve(null);
    });
  }

  compSearchM(mkey) {
    var tArr=[];
    return new Promise(async (resolve) => {
      const smkey = await this._companyRepo.search()
        .where('MASTERKEY').equals(mkey)
        .and('TBLNUM').equals(10)
        .return.all();
      if (smkey.length) {
        for (var spot in smkey) {
          const ttrr = await this._companyRepo.fetch(smkey[spot].entityId);
          tArr.push(ttrr.toJSON());
        }
        resolve(tArr);
      } else {
        resolve(null);
      }
    });
  }

walk.js

NN_walkd = async function(req, cnode, pnode, chain, lvl) {
  ...
  if (cnode[1]) {
    const sObj = await req.app.get('redis').compSearchK(cnode[1]);
    if (sObj) {
      int1 = (sObj.TBLNUM==1) ? null : sObj.CLIENTKEY;
      (async () => await NN_walkd(req, [sObj.COMPANYKEY,int1], cnode, Array.from(chain), tlvl))()
    }
  } else {
    const sArr = await req.app.get('redis').compSearchM(cnode[0]); 
    if (sArr.length) {
      for (sneaker in sArr) {
        (async () => await NN_walkd(req, [sArr[sneaker].COMPANYKEY,sArr[sneaker].CLIENTKEY], cnode, Array.from(chain), tlvl))()
      }
    } else {
      console.log('no more links on this chain: ',cnode);
    }
  }
}

CodePudding user response:

"doesn't matter if i have async or not here"

  compSearchK(ckey) {   // doesn't matter if I have a async or not here
    return new Promise(async (resolve) => {
      const sckey = await this._companyRepo.search()
        .where('COMPANYKEY').equals(ckey)
        .return.all();
      if (sckey.length) {
        const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
        resolve(ttrr.toJSON());
      } else
        resolve(null);
    });
  }

Of course it doesn't matter, because you're not using await inside of compSearchK!

You are using the explicit promise contructor anti-pattern. You should avoid it as it demonstrates lack of understanding. Here is compSearchK rewritten without the anti-pattern -

  async compSearchK(ckey) {
    // await key
    const sckey =
      await this._companyRepo.search()
        .where('COMPANYKEY').equals(ckey)
        .return.all();
    
    // return null if key is not found
    if (sckey.length == 0) return null;

    // otherwise get ttrr
    const ttrr = await this._companyRepo.fetch(sckey[0].entityId);

    // return ttrr as json
    return ttrr.toJSON();
  }
  • Related