Mengonversi kode JS duplikat menjadi fungsi urutan yang lebih tinggi
Saya memiliki blok kode yang digunakan kembali dan saya ingin menggunakan pemrograman fungsional untuk menghapus duplikasi ini.
Kode saya mengambil array item, membagi item menjadi batch 500 dan kemudian melakukan beberapa jenis pekerjaan pada mereka.
Fungsi pertama menghapus item dari database:
Hapus fungsi:
const deleteDocuments = async (documentReferences) => {
const batchesOf500 = Math.ceil(documentReferences.length / 500);
for(let batchNumber = 0; batchNumber < batchesOf500; batchNumber += 1) {
const batch = getBatchWriter();
const startingIndex = batchNumber * 500;
const maxIndex = startingIndex + 500;
for(let index = startingIndex; index < maxIndex; index += 1) {
if(index < documentReferences.length) {
const documentPath = documentReferences[index];
batch.delete(documentPath);
}
}
await batch.commit();
}
}
Fungsi kedua hampir identik tetapi alih-alih menghapus dari database, ia menulis ke database:
Tambahkan fungsi:
const writeToCollection = async (dataArray, collectionRef) => {
const batchesOf500 = Math.ceil(dataArray.length / 500);
for(let batchNumber = 0; batchNumber < batchesOf500; batchNumber += 1) {
const batch = getBatchWriter();
const startingIndex = batchNumber * 500;
const maxIndex = startingIndex + 500;
for(let index = startingIndex; index < maxIndex; index += 1) {
if(index < dataArray.length) {
const [key, value] = dataArray[index];
const doc = getDocFromPath(key);
batch.set(doc, value);
}
}
}
await batch.commit();
}
}
Fungsi-fungsi ini hampir identik, jadi saya telah menulis fungsi urutan yang lebih tinggi untuk melakukan sebagian besar pekerjaan kaki.
Fungsi urutan yang lebih tinggi:
const runFunctionInBatchesOf500 = (func, dataArray) => {
const batchesOf500 = Math.ceil(dataArray.length / 500);
for(let batchNumber = 0; batchNumber < batchesOf500; batchNumber += 1) {
const batch = this.firestore.batch();
const startingIndex = batchNumber * 500;
const maxIndex = startingIndex + 500;
for(let index = startingIndex; index < maxIndex; index += 1) {
const document = dataArray[index];
func(document, batch);
}
}
await batch.commit();
}
Dan untuk itu Anda dapat membuat fungsionalitas Anda sendiri untuk diterapkan ke setiap dokumen dan menggunakannya seperti ini:
const write = (document, batch) => {
const doc = getDocFromPath(key);
batch.set(doc, value);
};
await runFunctionInBatchesOf500(write, dataArray);
Ini semua berhasil tetapi saya pikir saya melewatkan sesuatu. Apakah ini penggunaan yang efisien dari fungsi orde tinggi? Apa solusi yang lebih elegan dan bergaya FP?
Jawaban
Dari ulasan singkat;
- Mengapa hardcode panjang batch menjadi 500?
- Mengapa tidak membuat panjang tumpukan menjadi konstanta yang bagus?
- Anda bahkan memiliki kode keras panjang dalam nama fungsi, yang sangat disayangkan
batchNumber++
lebih kanonik daripadabatchNumber += 1
- Saya akan pergi untuk
maxIndex = Math.min(startingIndex + 500, dataArray.length);
karena sekarang Anda memiliki banyak panggilan untukfunc
denganundefined
sebagaidocument
nilai await
membutuhkanrunFunctionInBatchesOf500
untukasync
(itu hilang sekarang)- Saya akan menggunakan
Array.prototype.slice()
untuk membuat batch sebagai array, dan kemudian menggunakannyaforEach
pada setiap slice / batch const doc = getDocFromPath(key);
<- dari manakey
asalnya, sebuah kejahatan global?
Saya pribadi akan menjadi agak jahat dengan menyesuaikan prototipe Array sehingga saya dapat terus merangkai, gaya FP;
Array.prototype.mapSlice = function arrrayMapSlice(n){
//Just return `this` if we get a non-sensical parameter
if(isNaN(n) || n <= 0){
return this;
}
let start = 0, out = [];
while(start < this.length){
out.push(this.slice(start, start+=n));
}
return out;
}
async function runBatches(list, f, batchSize){
batchSize = batchSize || 500;
list.mapSlice(batchSize).forEach(batch => {
const firestoreBatch = this.firestore.batch();
batch.forEach(document => f(document, firestoreBatch ));
});
await batch.commit();
}