중복 JS 코드를 고차 함수로 변환

Aug 20 2020

재사용되는 코드 블록이 있으며이 중복을 제거하기 위해 함수형 프로그래밍을 사용하고 싶습니다.

내 코드는 항목의 배열을 가져 와서 항목을 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 스타일 솔루션은 무엇일까요?

답변

6 konijn Aug 20 2020 at 14:59

짧은 리뷰에서;

  • 배치 길이를 500으로 하드 코딩하는 이유는 무엇입니까?
  • 배치 길이가 좋은 상수가 아닌 이유는 무엇입니까?
  • 함수 이름에 길이를 하드 코딩했습니다. 정말 불행합니다.
  • batchNumber++ 보다 정식 batchNumber += 1
  • 나는 위해 갔을 것입니다 maxIndex = Math.min(startingIndex + 500, dataArray.length);지금 당신이 전화를 많이 가지고 있기 때문에 funcundefinedA와 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();
}