how to accumulate promise return inside a loop
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
add a comment |
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
Start by not usingforEach
.
– 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 usemap
, but you don't actuallyreturn
anything useful from the callback, and you don't do anything with the array of results.
– Bergi
Nov 10 at 10:09
add a comment |
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
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
loops recursion promise
edited Nov 10 at 7:23
asked Nov 4 at 12:46
ctf0
3,69032232
3,69032232
Start by not usingforEach
.
– 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 usemap
, but you don't actuallyreturn
anything useful from the callback, and you don't do anything with the array of results.
– Bergi
Nov 10 at 10:09
add a comment |
Start by not usingforEach
.
– 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 usemap
, but you don't actuallyreturn
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
add a comment |
1 Answer
1
active
oldest
votes
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:
- Await getting the fileMetaData about EACH one of the files.
- Get each one of the original files' sizes and add those to 0.
- Check for if any files have nested files within.
- If so add those files to a list of files to recursively run this function.
- 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)
])
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 lexicalthis
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 thefiles.map
as well ?
– ctf0
Nov 10 at 7:27
|
show 1 more comment
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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:
- Await getting the fileMetaData about EACH one of the files.
- Get each one of the original files' sizes and add those to 0.
- Check for if any files have nested files within.
- If so add those files to a list of files to recursively run this function.
- 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)
])
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 lexicalthis
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 thefiles.map
as well ?
– ctf0
Nov 10 at 7:27
|
show 1 more comment
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:
- Await getting the fileMetaData about EACH one of the files.
- Get each one of the original files' sizes and add those to 0.
- Check for if any files have nested files within.
- If so add those files to a list of files to recursively run this function.
- 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)
])
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 lexicalthis
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 thefiles.map
as well ?
– ctf0
Nov 10 at 7:27
|
show 1 more comment
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:
- Await getting the fileMetaData about EACH one of the files.
- Get each one of the original files' sizes and add those to 0.
- Check for if any files have nested files within.
- If so add those files to a list of files to recursively run this function.
- 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)
])
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:
- Await getting the fileMetaData about EACH one of the files.
- Get each one of the original files' sizes and add those to 0.
- Check for if any files have nested files within.
- If so add those files to a list of files to recursively run this function.
- 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)
])
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 lexicalthis
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 thefiles.map
as well ?
– ctf0
Nov 10 at 7:27
|
show 1 more comment
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 lexicalthis
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 thefiles.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
|
show 1 more comment
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 actuallyreturn
anything useful from the callback, and you don't do anything with the array of results.– Bergi
Nov 10 at 10:09