Reputation: 3776
I'm getting an "Avoid nesting promises" (for jslint) for the following function. How can I write this without nesting promises?
function deleteUIDsFromDBForKey(rootkey, users_uids) {
return retrieveUIDsFromDBForKey(rootkey)
.then(uids => {
let diff = uids.diff(users_uids)
let deletes = []
diff.forEach(key => {
deletes.push(firebase.database().ref(rootkey + "/" + key).remove())
})
return Promise.all(deletes)
.then(value => {
return diff
})
})
}
Upvotes: 0
Views: 2182
Reputation: 707158
I this case, I think jsLint is just steering you wrong into more complicated code. Sometimes, you get that from a linter and the best option in that case is to bypass the linter for a specific line of code or function or a specific linter rule.
This is the simplest and clearest implementation of your code I can think of (which should be your priority):
function deleteUIDsFromDBForKey(rootkey, users_uids) {
return retrieveUIDsFromDBForKey(rootkey).then(uids => {
const diff = uids.diff(users_uids);
// wait for all deletes to be done, then return diff
return Promise.all(diff.map(key => {
return firebase.database().ref(rootkey + "/" + key).remove();
})).then(() => diff);
});
}
Or, using Bluebird's .map()
, you can do this:
// using Bluebird's Promise.map()
function deleteUIDsFromDBForKey(rootkey, users_uids) {
return retrieveUIDsFromDBForKey(rootkey).then(uids => {
const diff = uids.diff(users_uids);
// wait for all deletes to be done, then return diff
return Promise.map(diff, key => {
return firebase.database().ref(rootkey + "/" + key).remove();
}).then(() => diff);
});
}
Or, using async/await:
async function deleteUIDsFromDBForKey(rootkey, users_uids) {
const uids = await retrieveUIDsFromDBForKey(rootkey);
const diff = uids.diff(users_uids);
await Promise.all(diff.map(key => {
return firebase.database().ref(rootkey + "/" + key).remove();
}));
return diff;
}
I don't have an ES7-capable jsLint installed, but the last option should avoid the nesting warning. The first two, probably not, but trying to avoid that warning will just make worse code so IMO, you should just disable the warning.
Upvotes: 0
Reputation: 350079
The last then
can be moved up to the main chain by returning the Promise.all
result:
function deleteUIDsFromDBForKey(rootkey, users_uids) {
let diff;
return retrieveUIDsFromDBForKey(rootkey)
.then(uids => {
diff = uids.diff(users_uids)
let deletes = []
diff.forEach(key => {
deletes.push(firebase.database().ref(rootkey + "/" + key).remove())
})
return Promise.all(deletes)
})
.then(value => {
return diff
})
}
Note that for this to work, the scope of the variable diff
needs to be enlarged, as done above. Alternatively you could add diff
to the arguments passed to Promise.all
, so you get access to diff
as a promised value:
function deleteUIDsFromDBForKey(rootkey, users_uids) {
return retrieveUIDsFromDBForKey(rootkey)
.then(uids => {
let diff = uids.diff(users_uids)
let deletes = []
diff.forEach(key => {
deletes.push(firebase.database().ref(rootkey + "/" + key).remove())
})
return Promise.all([diff, ...deletes])
})
.then(([diff]) => {
return diff
})
}
Unrelated to your question, but you could use map
instead of forEach
with push
:
let deletes = diff.map(key => {
return firebase.database().ref(rootkey + "/" + key).remove()
})
Upvotes: 3