Search code examples
javascriptnode.jsasynchronousnode-async

return true actually returns undefined using async


I'm trying to do something if the value is not exist, so I can update it. but isExist function always return undefined. what can I do with this?

reference: Ero is already defined.

async.forEachOf(idArray, function(value, key, cb) {
    rp(baseURL + value)
      .then(function(json) {
          if (!isExist(json)) {
              // do something
            } else {
                console.log(isExist(json), "It's not video or exists");
            }
        })
    .catch(function(err) {
      console.error(err);
    })
    cb();
  }, function() {
    res.status(200)
  });
});

function isExist(data) {
  let parsedData = JSON.parse(data);
  if (parsedData.items[0].type === 'Video') {
    Ero.find({
      videoUri: parsedData.items[0].url_mp4
    }, function(err, docs) {
      if (docs.length) {
          return true;
      } else {
          return false;
      }
    })
  } else {
      return false;
  }
}

Solution

  • Let's look at your isExist function.

    function isExist(data) {
      let parsedData = JSON.parse(data);
      if (parsedData.items[0].type === 'Video') {
        Ero.find({
          videoUri: parsedData.items[0].url_mp4
        }, function(err, docs) {
          if (docs.length) {
              return true;
          } else {
              return false;
          }
        })
      } else {
          return false;
      }
    }
    

    In that function you have two branches at the conditional. When the condition is false the else block will run – this returns false. When the condition is true the first block will run however there is no return statement, therefore implicitly returning undefined.

    You say "why does it not have a return statement?", I'm pretty sure I have one.

    It looks like you have one here.

    if (docs.length) {
      return true;
    } else {
      return false;
    }
    

    However look at which function it is returning out of. It is only returning out of the callback function passed to Ero.find, it does not return out of isExist.

    You ask "what can I do about this?".

    I am assuming Ero.find is an asynchronous function, therefore isExist will become an asynchronous function too. To do async functions in JavaScript you can use Promises or async functions.

    Here's some example code of what isExist might look like with a Promise.

    function isExist(data) {
      /**
       * `isExist` returns a Promise. This means the function _promises_ to have a value resolved in the future.
       */
      return new Promise((resolve, reject) => {
        let parsedData = JSON.parse(data);
        if (parsedData.items[0].type === 'Video') {
          Ero.find({
            videoUri: parsedData.items[0].url_mp4
          }, function(err, docs) {
            if (docs.length) {
              /**
               * Once `Ero.find` has completed, `resolve` `isExist` with a value of `true`, otherwise `resolve` `isExist` with a value of `false`.
               */
              resolve(true);
            } else {
              resolve(false);
            }
          })
        } else {
          /**
           * You can resolve a Promise even without performing an asynchronous operation.
           */
          resolve(false);
        }
      });
    }
    

    Further reading