การแปลงรหัส JS ที่ซ้ำกันเป็นฟังก์ชันลำดับที่สูงขึ้น
ฉันมีบล็อกของโค้ดที่ใช้ซ้ำและต้องการใช้การเขียนโปรแกรมเชิงฟังก์ชันเพื่อลบการทำซ้ำนี้
รหัสของฉันใช้อาร์เรย์ของรายการแยกรายการออกเป็นชุดละ 500 แล้วทำงานบางอย่างกับรายการเหล่านั้น
ในฟังก์ชันแรกจะลบรายการออกจากฐานข้อมูล:
ลบฟังก์ชัน:
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();
}
}
ฟังก์ชันที่สองเกือบจะเหมือนกัน แต่แทนที่จะลบออกจากฐานข้อมูลฟังก์ชันนี้จะเขียนไปยังฐานข้อมูล:
เพิ่มฟังก์ชัน:
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();
}
}
ฟังก์ชันเหล่านี้แทบจะเหมือนกันดังนั้นฉันจึงเขียนฟังก์ชันลำดับที่สูงกว่าเพื่อทำงานส่วนใหญ่
ฟังก์ชั่นการสั่งซื้อที่สูงขึ้น:
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();
}
และคุณสามารถสร้างฟังก์ชันการทำงานของคุณเองเพื่อใช้กับเอกสารแต่ละฉบับและใช้งานได้ดังนี้:
const write = (document, batch) => {
const doc = getDocFromPath(key);
batch.set(doc, value);
};
await runFunctionInBatchesOf500(write, dataArray);
ทั้งหมดนี้ใช้ได้ผล แต่ฉันคิดว่าฉันขาดอะไรไป นี่เป็นการใช้ฟังก์ชันลำดับที่สูงขึ้นอย่างมีประสิทธิภาพหรือไม่ โซลูชันสไตล์ FP ที่หรูหรากว่าจะเป็นอย่างไร
คำตอบ
จากบทวิจารณ์สั้น ๆ ;
- ทำไมต้องฮาร์ดโค้ดความยาวแบทช์เป็น 500
- ทำไมไม่ให้ความยาวแบทช์เป็นค่าคงที่ที่ดี?
- คุณได้เข้ารหัสความยาวในชื่อฟังก์ชันอย่างหนักซึ่งเป็นเรื่องที่โชคร้ายจริงๆ
batchNumber++
เป็นที่ยอมรับมากกว่าbatchNumber += 1
- ฉันจะได้ไป
maxIndex = Math.min(startingIndex + 500, dataArray.length);
เพราะตอนนี้คุณมีจำนวนมากของสายให้func
กับundefined
เป็นdocument
มูลค่า await
ต้องrunFunctionInBatchesOf500
เป็นasync
(ตอนนี้หายไป)- ฉันจะใช้
Array.prototype.slice()
เพื่อสร้างแบทช์เป็นอาร์เรย์แล้วใช้forEach
กับแต่ละชิ้น / แบทช์ const doc = getDocFromPath(key);
<-key
มาจากไหนโลกที่ชั่วร้าย?
โดยส่วนตัวแล้วฉันจะเป็นคนชั่วเล็กน้อยโดยการปรับต้นแบบ Array เพื่อที่ฉันจะสามารถผูกมัดสไตล์ 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();
}