how to accumulate promise return inside a loop










1














for example am trying to recursively get the file size of all items under a folder in cordova so i have something like



getDirSize(path) 
return this.listDir(path).then((data) =>
let size = 0

data.dirs.map((dir) =>
size += this.getRecursiveSize(dir.files)
)

if (data.files.length)
size += this.getRecursiveSize(data.files)


return size
)


getRecursiveSize(files)
let size = 0

files.map((item) =>
this.getFileMeta(item.url).then((file) =>
size += file.size
)

if (item.files)
size += this.getRecursiveSize(item.files)

)

return size



which is called through



getDirSize(path).then((size) => 
console.log(size)
)


however this doesn't work because the getFileMeta() is a promise, i know about promise.all() but am not sure how to use it properly to get the final size of all items.










share|improve this question























  • Start by not using forEach.
    – Bergi
    Nov 4 at 14:58










  • You can't actually write a function that returns the size. You need to return a promise, because if the results of getFileMeta aren't immediately available, then they will have to be calculated after your function returns.
    – Matt Timmermans
    Nov 4 at 15:25










  • @MattTimmermans can u add an example ?
    – ctf0
    Nov 4 at 16:23






  • 1




    You now use map, but you don't actually return anything useful from the callback, and you don't do anything with the array of results.
    – Bergi
    Nov 10 at 10:09
















1














for example am trying to recursively get the file size of all items under a folder in cordova so i have something like



getDirSize(path) 
return this.listDir(path).then((data) =>
let size = 0

data.dirs.map((dir) =>
size += this.getRecursiveSize(dir.files)
)

if (data.files.length)
size += this.getRecursiveSize(data.files)


return size
)


getRecursiveSize(files)
let size = 0

files.map((item) =>
this.getFileMeta(item.url).then((file) =>
size += file.size
)

if (item.files)
size += this.getRecursiveSize(item.files)

)

return size



which is called through



getDirSize(path).then((size) => 
console.log(size)
)


however this doesn't work because the getFileMeta() is a promise, i know about promise.all() but am not sure how to use it properly to get the final size of all items.










share|improve this question























  • Start by not using forEach.
    – Bergi
    Nov 4 at 14:58










  • You can't actually write a function that returns the size. You need to return a promise, because if the results of getFileMeta aren't immediately available, then they will have to be calculated after your function returns.
    – Matt Timmermans
    Nov 4 at 15:25










  • @MattTimmermans can u add an example ?
    – ctf0
    Nov 4 at 16:23






  • 1




    You now use map, but you don't actually return anything useful from the callback, and you don't do anything with the array of results.
    – Bergi
    Nov 10 at 10:09














1












1








1







for example am trying to recursively get the file size of all items under a folder in cordova so i have something like



getDirSize(path) 
return this.listDir(path).then((data) =>
let size = 0

data.dirs.map((dir) =>
size += this.getRecursiveSize(dir.files)
)

if (data.files.length)
size += this.getRecursiveSize(data.files)


return size
)


getRecursiveSize(files)
let size = 0

files.map((item) =>
this.getFileMeta(item.url).then((file) =>
size += file.size
)

if (item.files)
size += this.getRecursiveSize(item.files)

)

return size



which is called through



getDirSize(path).then((size) => 
console.log(size)
)


however this doesn't work because the getFileMeta() is a promise, i know about promise.all() but am not sure how to use it properly to get the final size of all items.










share|improve this question















for example am trying to recursively get the file size of all items under a folder in cordova so i have something like



getDirSize(path) 
return this.listDir(path).then((data) =>
let size = 0

data.dirs.map((dir) =>
size += this.getRecursiveSize(dir.files)
)

if (data.files.length)
size += this.getRecursiveSize(data.files)


return size
)


getRecursiveSize(files)
let size = 0

files.map((item) =>
this.getFileMeta(item.url).then((file) =>
size += file.size
)

if (item.files)
size += this.getRecursiveSize(item.files)

)

return size



which is called through



getDirSize(path).then((size) => 
console.log(size)
)


however this doesn't work because the getFileMeta() is a promise, i know about promise.all() but am not sure how to use it properly to get the final size of all items.







loops recursion promise






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 7:23

























asked Nov 4 at 12:46









ctf0

3,69032232




3,69032232











  • Start by not using forEach.
    – Bergi
    Nov 4 at 14:58










  • You can't actually write a function that returns the size. You need to return a promise, because if the results of getFileMeta aren't immediately available, then they will have to be calculated after your function returns.
    – Matt Timmermans
    Nov 4 at 15:25










  • @MattTimmermans can u add an example ?
    – ctf0
    Nov 4 at 16:23






  • 1




    You now use map, but you don't actually return anything useful from the callback, and you don't do anything with the array of results.
    – Bergi
    Nov 10 at 10:09

















  • Start by not using forEach.
    – Bergi
    Nov 4 at 14:58










  • You can't actually write a function that returns the size. You need to return a promise, because if the results of getFileMeta aren't immediately available, then they will have to be calculated after your function returns.
    – Matt Timmermans
    Nov 4 at 15:25










  • @MattTimmermans can u add an example ?
    – ctf0
    Nov 4 at 16:23






  • 1




    You now use map, but you don't actually return anything useful from the callback, and you don't do anything with the array of results.
    – Bergi
    Nov 10 at 10:09
















Start by not using forEach.
– Bergi
Nov 4 at 14:58




Start by not using forEach.
– Bergi
Nov 4 at 14:58












You can't actually write a function that returns the size. You need to return a promise, because if the results of getFileMeta aren't immediately available, then they will have to be calculated after your function returns.
– Matt Timmermans
Nov 4 at 15:25




You can't actually write a function that returns the size. You need to return a promise, because if the results of getFileMeta aren't immediately available, then they will have to be calculated after your function returns.
– Matt Timmermans
Nov 4 at 15:25












@MattTimmermans can u add an example ?
– ctf0
Nov 4 at 16:23




@MattTimmermans can u add an example ?
– ctf0
Nov 4 at 16:23




1




1




You now use map, but you don't actually return anything useful from the callback, and you don't do anything with the array of results.
– Bergi
Nov 10 at 10:09





You now use map, but you don't actually return anything useful from the callback, and you don't do anything with the array of results.
– Bergi
Nov 10 at 10:09













1 Answer
1






active

oldest

votes


















0














So you can put all of the calls to getFileMeta() into an array using map and Promise.all. Promise.all will take a an array of promises and set whatever is resolved within each into an array.



So you get back an array of fileMetaData in this case, which you can use as any other array (after the Promise.all is finished -- using .then or await)..



If it (aka getFileMeta) already returns a promise:



const filesMetaData = Promise.all(files.map(file => this.getFileMeta(file.url)))
filesMetaData.then(
fileMetaData // became an array here because of Promise.all
=> fileMetaData.reduce((accumulatedSize, file) =>
accumulatedSize += file.size
return accumulatedSize
)


Or if you are using a later version of node then you can use asynchronous javascript with async/await which is pretty cool!



In pseudo-code the strategy is:



  1. Await getting the fileMetaData about EACH one of the files.

  2. Get each one of the original files' sizes and add those to 0.

  3. Check for if any files have nested files within.

  4. If so add those files to a list of files to recursively run this function.

  5. If none of the files have nested files return the count for the parent files.




const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])








share|improve this answer






















  • Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
    – ctf0
    Nov 4 at 13:12











  • arrow functions have a lexical this so there's no need to use _this in your second example
    – user633183
    Nov 4 at 13:27










  • does this work? I think it should or it might need slight tweaking
    – Zargold
    Nov 4 at 17:46










  • hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
    – Zargold
    Nov 8 at 3:20










  • @Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
    – ctf0
    Nov 10 at 7:27











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53140956%2fhow-to-accumulate-promise-return-inside-a-loop%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














So you can put all of the calls to getFileMeta() into an array using map and Promise.all. Promise.all will take a an array of promises and set whatever is resolved within each into an array.



So you get back an array of fileMetaData in this case, which you can use as any other array (after the Promise.all is finished -- using .then or await)..



If it (aka getFileMeta) already returns a promise:



const filesMetaData = Promise.all(files.map(file => this.getFileMeta(file.url)))
filesMetaData.then(
fileMetaData // became an array here because of Promise.all
=> fileMetaData.reduce((accumulatedSize, file) =>
accumulatedSize += file.size
return accumulatedSize
)


Or if you are using a later version of node then you can use asynchronous javascript with async/await which is pretty cool!



In pseudo-code the strategy is:



  1. Await getting the fileMetaData about EACH one of the files.

  2. Get each one of the original files' sizes and add those to 0.

  3. Check for if any files have nested files within.

  4. If so add those files to a list of files to recursively run this function.

  5. If none of the files have nested files return the count for the parent files.




const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])








share|improve this answer






















  • Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
    – ctf0
    Nov 4 at 13:12











  • arrow functions have a lexical this so there's no need to use _this in your second example
    – user633183
    Nov 4 at 13:27










  • does this work? I think it should or it might need slight tweaking
    – Zargold
    Nov 4 at 17:46










  • hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
    – Zargold
    Nov 8 at 3:20










  • @Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
    – ctf0
    Nov 10 at 7:27
















0














So you can put all of the calls to getFileMeta() into an array using map and Promise.all. Promise.all will take a an array of promises and set whatever is resolved within each into an array.



So you get back an array of fileMetaData in this case, which you can use as any other array (after the Promise.all is finished -- using .then or await)..



If it (aka getFileMeta) already returns a promise:



const filesMetaData = Promise.all(files.map(file => this.getFileMeta(file.url)))
filesMetaData.then(
fileMetaData // became an array here because of Promise.all
=> fileMetaData.reduce((accumulatedSize, file) =>
accumulatedSize += file.size
return accumulatedSize
)


Or if you are using a later version of node then you can use asynchronous javascript with async/await which is pretty cool!



In pseudo-code the strategy is:



  1. Await getting the fileMetaData about EACH one of the files.

  2. Get each one of the original files' sizes and add those to 0.

  3. Check for if any files have nested files within.

  4. If so add those files to a list of files to recursively run this function.

  5. If none of the files have nested files return the count for the parent files.




const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])








share|improve this answer






















  • Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
    – ctf0
    Nov 4 at 13:12











  • arrow functions have a lexical this so there's no need to use _this in your second example
    – user633183
    Nov 4 at 13:27










  • does this work? I think it should or it might need slight tweaking
    – Zargold
    Nov 4 at 17:46










  • hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
    – Zargold
    Nov 8 at 3:20










  • @Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
    – ctf0
    Nov 10 at 7:27














0












0








0






So you can put all of the calls to getFileMeta() into an array using map and Promise.all. Promise.all will take a an array of promises and set whatever is resolved within each into an array.



So you get back an array of fileMetaData in this case, which you can use as any other array (after the Promise.all is finished -- using .then or await)..



If it (aka getFileMeta) already returns a promise:



const filesMetaData = Promise.all(files.map(file => this.getFileMeta(file.url)))
filesMetaData.then(
fileMetaData // became an array here because of Promise.all
=> fileMetaData.reduce((accumulatedSize, file) =>
accumulatedSize += file.size
return accumulatedSize
)


Or if you are using a later version of node then you can use asynchronous javascript with async/await which is pretty cool!



In pseudo-code the strategy is:



  1. Await getting the fileMetaData about EACH one of the files.

  2. Get each one of the original files' sizes and add those to 0.

  3. Check for if any files have nested files within.

  4. If so add those files to a list of files to recursively run this function.

  5. If none of the files have nested files return the count for the parent files.




const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])








share|improve this answer














So you can put all of the calls to getFileMeta() into an array using map and Promise.all. Promise.all will take a an array of promises and set whatever is resolved within each into an array.



So you get back an array of fileMetaData in this case, which you can use as any other array (after the Promise.all is finished -- using .then or await)..



If it (aka getFileMeta) already returns a promise:



const filesMetaData = Promise.all(files.map(file => this.getFileMeta(file.url)))
filesMetaData.then(
fileMetaData // became an array here because of Promise.all
=> fileMetaData.reduce((accumulatedSize, file) =>
accumulatedSize += file.size
return accumulatedSize
)


Or if you are using a later version of node then you can use asynchronous javascript with async/await which is pretty cool!



In pseudo-code the strategy is:



  1. Await getting the fileMetaData about EACH one of the files.

  2. Get each one of the original files' sizes and add those to 0.

  3. Check for if any files have nested files within.

  4. If so add those files to a list of files to recursively run this function.

  5. If none of the files have nested files return the count for the parent files.




const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])








const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])





const recursivelyGetSize = async (files) => 
if (!files.length) // recursive condition
return 0

const filesMetaData = await Promise.all(
files.map(file => this.getFileMeta(file.url))
) // became an array of files here because of Promise.all
const count = fileMetaData.reduce(
(accumulatedSize, file) => accumulatedSize + file.size,
0
)
const filesWithFiles = filesMetaData.filter(file => file.files.length)
if (!filesWithFiles.length)
return count

// not sure if you need await here because
// return by default has a built in await
return count + await recursivelyGetSize([
...filesWithFiles.map(file => file.files)
])






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 12 at 2:03

























answered Nov 4 at 12:54









Zargold

706420




706420











  • Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
    – ctf0
    Nov 4 at 13:12











  • arrow functions have a lexical this so there's no need to use _this in your second example
    – user633183
    Nov 4 at 13:27










  • does this work? I think it should or it might need slight tweaking
    – Zargold
    Nov 4 at 17:46










  • hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
    – Zargold
    Nov 8 at 3:20










  • @Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
    – ctf0
    Nov 10 at 7:27

















  • Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
    – ctf0
    Nov 4 at 13:12











  • arrow functions have a lexical this so there's no need to use _this in your second example
    – user633183
    Nov 4 at 13:27










  • does this work? I think it should or it might need slight tweaking
    – Zargold
    Nov 4 at 17:46










  • hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
    – Zargold
    Nov 8 at 3:20










  • @Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
    – ctf0
    Nov 10 at 7:27
















Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
– ctf0
Nov 4 at 13:12





Also not sure if when you say getFileMeta is a promise if it returns a promise or what, yes it does, also can u plz update the example with the recursive condition ?
– ctf0
Nov 4 at 13:12













arrow functions have a lexical this so there's no need to use _this in your second example
– user633183
Nov 4 at 13:27




arrow functions have a lexical this so there's no need to use _this in your second example
– user633183
Nov 4 at 13:27












does this work? I think it should or it might need slight tweaking
– Zargold
Nov 4 at 17:46




does this work? I think it should or it might need slight tweaking
– Zargold
Nov 4 at 17:46












hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
– Zargold
Nov 8 at 3:20




hi I think I had updated it to give you the full recursive version. Let me know if ther were issues.
– Zargold
Nov 8 at 3:20












@Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
– ctf0
Nov 10 at 7:27





@Zargold sorry for the delay i just saw ur comment now, thanx for the update, can we a recursive check inside the files.map as well ?
– ctf0
Nov 10 at 7:27


















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53140956%2fhow-to-accumulate-promise-return-inside-a-loop%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

Syphilis

Darth Vader #20