0👍
Several issues:
-
You are applying a
.filter
call on the promises returned by the.map
call, but promises don’t have astatus
property to filter by. You can only filter on the resolved values, not on the promises. So you first need to await the resolution of theallSettled
promise before you can start filtering. -
splice
expects the insert-values as individual arguments, not as an array. So use the spread syntax -
As you want to populate your
successIds
withid
values, and your api returns objects withid
andsuccess
properties, you still need to extract thatid
property from each object.
Here is a correction (I removed the vue dependecies):
const fakeApiRequest = (id) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = id % 2;
success ? resolve({ id, success}) : reject({ success });
}, 200);
});
};
const app = {
data() {
return {
// Fetch ids
ids: [1, 2, 3, 4, 5, 6],
// Complete ids
successIds: [],
};
},
methods: {
async send() {
const results = await Promise.allSettled(
this.ids.map(fakeApiRequest)
);
const ids = results.filter((settled) => settled.status === "fulfilled")
.map((settled) => settled.value.id);
this.successIds.splice(0, 0, ...ids);
console.log(this.successIds); // for this demo only
},
},
};
// Mimic vue
app.methods.send.call(app.data());
1👍
You can only apply filters on the awaited results of Promise.allSettled()
. So you either do just that (await
and then apply the filters on the awaited result) or place the filters on its then
:
Working example:
const { createApp, defineComponent } = Vue;
const fakeApiRequest = (id) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = id % 2;
success ? resolve({ id, success }) : reject({ success });
}, 2000);
});
};
const Test = defineComponent({
template: "#test",
data() {
return {
ids: [1, 2, 3, 4, 5, 6],
successIds: [],
};
},
methods: {
async send() {
this.successIds = []
this.successIds = await Promise.allSettled(
this.ids.map(fakeApiRequest)
).then((results) =>
results
.filter(({ status }) => status === "fulfilled")
.map(({ value }) => value.id)
);
},
},
});
createApp({
components: { Test },
}).mount("#app");
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="app">
<test />
</div>
<template id="test">
<div class="hello">
<h1>Example 2</h1>
<input @click="send" type="button" value="Send" />
<div class="out" v-if="successIds.length">{{ successIds }}</div>
</div>
</template>
Side note: you don’t need to splice
the results to keep reactivity. If you lose reactivity, you should ask a separate question about it, providing enough detail. As you can see, it works perfectly fine in my example.