I have a reduce function in my Vue app which works perfectly as far as the logic is concerned but it's incredibly slow.
Luckily, I experimented and found that it's the if/else at the bottom causing the bottleneck (noticable with thousands of records). If I take out the section noted below, it runs quickly.
Should I plug that portion into a different function and just call it at the end of the reduce, or is there another way (that's not obvious to me) that will keep things clean and functional?
<script>
const reduceFunction = (rows) =>
rows .reduce(
(a, row) => {
const employee = a [row .employee] || (a [row .employee] = {dates: {}, total_categories:0, total_items: 0, area: '', group: ''})
const date = employee .dates [row .itemDate] || (employee .dates [row .itemDate] = {categories: 0, qty: 0, total_categories: 0, unavailable: 0, orders: {}})
date.categories = row.categories_per_item * row.qty
date.qty = row.qty
date.total_categories = date.categories
const order = date .orders [row .order_number] || (date .orders [row .order_number] = {itemDate: '', skus: {}})
order.itemDate = row.itemDate;
const sku = order .skus [row .sku] || (order .skus [row .sku] = {categories: '', qty: '', itemDate: '', expected: '', created: '', unavailable: 0, available:0})
sku.categories = row.categories_per_item
sku.qty = row.qty
sku.itemDate = row.itemDate
sku.expected = row.shipDate
sku.created = row.created_date
sku.heir_id = row.heir_identifier
employee.total_categories = ( row.categories_per_item * row.qty)
employee.total_items = ( row.qty)
employee.area = row.area
employee.group = row.group_name
employee.warehouse = row.warehouse
employee.locale = row.locale
const foundKit = vm.$data.kitsData.find((kit) => kit.heir_identifier === sku.heir_id)
if (foundKit) {
new_avail = 10;
if(sku.qty > new_avail){
status.status = "Not available";
date.unavailable = 1
sku.unavailable = 1
}else{
status.status = "Available"
}
}else{
status.status = "No item found"
}
return a
},
{}
);
var vm =
new Vue({
el: "#app",
data: {
rows: [
{
employee: "Adam",
sku: "A1453",
categories_per_item: "15",
area: "1",
itemDate: "2021-11-02",
qty: 37,
group_name: "managers",
warehouse: "3",
order_number: "1234",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC3"
},
{
employee: "Joan",
sku: "A1453",
categories_per_item: "15",
area: "1a",
itemDate: "2021-11-02",
qty: 17,
group_name: "managers",
warehouse: "3",
order_number: "34578",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC3"
},
{
employee: "Bill",
sku: "A1453",
categories_per_item: "15",
area: "1",
itemDate: "2021-11-03",
qty: 57,
group_name: "managers",
warehouse: "3",
order_number: "2345",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC3"
},
{
employee: "PJ",
sku: "A6512",
categories_per_item: "150",
area: "2",
itemDate: "2021-11-03",
qty: 20,
group_name: "managers",
warehouse: "3",
order_number: "34567",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier:"ABC1"
}
]
},
methods: {
},
computed: {
employeeData() {
console.log('employee data')
employeeRows = reduceFunction(this.rows)
return employeeRows
console.log(employeeRows)
},
dates() {
return Array.from(Array(11), (_, i) => new Date(Date.now() i * 86400000).toISOString().slice(0,10))
}
}
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<tr v-for="(value, employee) in employeeData" :key="employee">
<td>@{{employee}}</td>
<td v-for="date in dates" :key="date" >
<div v-for="(dateInfo, dateValue) in value.dates" :key="dateValue" >
<div v-if="dateValue == date ">
@{{ dateInfo.total_categories }}
</div>
</div>
</td>
</tr>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
It's almost certainly the find()
that's the bottleneck, not the if
.
Create a Set
containing all the heir identifiers, then you can quickly check if the current identifier exists.
const reduceFunction = (rows) => {
let heirs = new Set(vm.$data.kitsData.map(kit => kit.heir_identifier));
return rows.reduce(
(a, row) => {
const employee = a[row.employee] || (a[row.employee] = {
dates: {},
total_categories: 0,
total_items: 0,
area: '',
group: ''
})
const date = employee.dates[row.itemDate] || (employee.dates[row.itemDate] = {
categories: 0,
qty: 0,
total_categories: 0,
unavailable: 0,
orders: {}
})
date.categories = row.categories_per_item * row.qty
date.qty = row.qty
date.total_categories = date.categories
const order = date.orders[row.order_number] || (date.orders[row.order_number] = {
itemDate: '',
skus: {}
})
order.itemDate = row.itemDate;
const sku = order.skus[row.sku] || (order.skus[row.sku] = {
categories: '',
qty: '',
itemDate: '',
expected: '',
created: '',
unavailable: 0,
available: 0
})
sku.categories = row.categories_per_item
sku.qty = row.qty
sku.itemDate = row.itemDate
sku.expected = row.shipDate
sku.created = row.created_date
sku.heir_id = row.heir_identifier
employee.total_categories = ( row.categories_per_item * row.qty)
employee.total_items = ( row.qty)
employee.area = row.area
employee.group = row.group_name
employee.warehouse = row.warehouse
employee.locale = row.locale
if (heirs.has(sku.heir_id) {
new_avail = 10;
if (sku.qty > new_avail) {
status.status = "Not available";
date.unavailable = 1
sku.unavailable = 1
} else {
status.status = "Available"
}
} else {
status.status = "No item found"
}
return a
}, {}
)
}
};
var vm =
new Vue({
el: "#app",
data: {
rows: [{
employee: "Adam",
sku: "A1453",
categories_per_item: "15",
area: "1",
itemDate: "2021-11-02",
qty: 37,
group_name: "managers",
warehouse: "3",
order_number: "1234",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier: "ABC3"
},
{
employee: "Joan",
sku: "A1453",
categories_per_item: "15",
area: "1a",
itemDate: "2021-11-02",
qty: 17,
group_name: "managers",
warehouse: "3",
order_number: "34578",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier: "ABC3"
},
{
employee: "Bill",
sku: "A1453",
categories_per_item: "15",
area: "1",
itemDate: "2021-11-03",
qty: 57,
group_name: "managers",
warehouse: "3",
order_number: "2345",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier: "ABC3"
},
{
employee: "PJ",
sku: "A6512",
categories_per_item: "150",
area: "2",
itemDate: "2021-11-03",
qty: 20,
group_name: "managers",
warehouse: "3",
order_number: "34567",
locale: "1",
shipDate: "2020-02-02",
created_date: "2020-01-01",
heir_identifier: "ABC1"
}
]
},
methods: {
},
computed: {
employeeData() {
console.log('employee data')
employeeRows = reduceFunction(this.rows)
return employeeRows
console.log(employeeRows)
},
dates() {
return Array.from(Array(11), (_, i) => new Date(Date.now() i * 86400000).toISOString().slice(0, 10))
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<tr v-for="(value, employee) in employeeData" :key="employee">
<td>@{{employee}}</td>
<td v-for="date in dates" :key="date">
<div v-for="(dateInfo, dateValue) in value.dates" :key="dateValue">
<div v-if="dateValue == date ">
@{{ dateInfo.total_categories }}
</div>
</div>
</td>
</tr>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>