Search code examples
javascriptfunctionfunctional-programmingabstraction

Name for a function that maps and returns a resolved array of promises?


Maybe this is a stupid ask but I recently found myself using this abstraction often:

async function giveMeAName(cbAsync, initValue) {
  return await Promise.all(
    initValue.map(cbAsync),
  );
}

Question: Is this a common task to anyone else? If so, does it have a name? If not, maybe it's only partly realize, so does it remind you of anything? Otherwise, I can just delete the question.

Currently I'm using this function for this set of instructions. Code below will get all directories of a path and collect all directories that have a package.json within:

const directories = (await getDirNamesByPath(rootPath));
const paths = await giveMeAName(addExistAdaptor, directories.map(joinPathWithName(rootPath)));
return await giveMeAName(collectJson, paths.filter(hasPath));

Solution

  • You asked a related question a couple days ago that I tried helping you with, but you never replied :(

    I've answered similar questions (here and here) that have generalised this pattern -

    const Parallel = p =>
      ( { map: async f =>
            Promise .all ((await p) .map (x => f (x)))
        , filter: async f =>
            Promise .all ((await p) .filter (x => f (x)))
        , flatMap: async f =>
            Promise .all ((await p) .map (x => f (x))) .then (ys => [] .concat (...ys))
        , // ...
        }
      )
    

    You can see it being used in this way with files, which recursively lists all paths to all files in a directory and its subdirectories -

    const { readdir, stat } =
      require ("fs") .promises
    
    const { join } =
      require ("path")
    
    const files = async (path = ".") =>
      (await stat (path)) .isDirectory ()
        ? Parallel (readdir (path))
            .flatMap (f => files (join (path, f)))
        : [ path ]
    

    And a specialisation, search, which returns all paths matching a query -

    const { basename } =
      require ("path")
    
    const search = async (query, path = ".") =>
      Parallel (files (path))
        .filter (f => basename (f) === query)
    

    And readPackages which recursively reads all package.json files at a specified path -

    const { readFile } =
      require ("fs") .promises
    
    const readPackages = async (path = ".") =>
      Parallel (search ("package.json", path))
        .map (readFile)
        .then
          ( buffers =>
              buffers .map (b => JSON .parse (String (b)))
          )
    

    Finally, a slightly more complex example, dirs, which works like files but recursively lists directories only. The level of recursion can be controlled by the depth parameter -

    const dirs = async (path = ".", depth = Infinity) =>
      (await stat (path)) .isDirectory ()
        ? depth === -1
            ? []
            : Parallel (readdir (path))
                .flatMap (f => dirs (join (path, f), depth - 1))
                .then (results => [ path, ...results ])
        : []
    

    To see what these programs look like without the Parallel module, see the linked Q&A's above.