Как упростить setTimeout в ReactJS

Вот реализация, которая использует рекурсию для сортировки по любому числу полей сортировки от 1 до бесконечного. Вы передаете ему массив результатов, который представляет собой массив объектов результатов для сортировки, и массив sorts, который представляет собой массив объектов сортировки, определяющих сортировку. У каждого объекта сортировки должен быть ключ «выбрать» для имени ключа, которое он сортирует, и ключ «порядок», который является строкой, обозначающей «восходящий» или «нисходящий».

sortMultiCompare = (a, b, sorts) => {
    let select = sorts[0].select
    let order = sorts[0].order
    if (a[select] < b[select]) {
        return order == 'ascending' ? -1 : 1
    } 
    if (a[select] > b[select]) {
        return order == 'ascending' ? 1 : -1
    }
    if(sorts.length > 1) {
        let remainingSorts = sorts.slice(1)
        return this.sortMultiCompare(a, b, remainingSorts)
    }
    return 0
}

sortResults = (results, sorts) => {
    return results.sort((a, b) => {
        return this.sortMultiCompare(a, b, sorts)
    })
}

// example inputs
const results = [
    {
        "LastName": "Doe",
        "FirstName": "John",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Doe",
        "FirstName": "Jane",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Johnson",
        "FirstName": "Kevin",
        "MiddleName": "Bill"
    }
]

const sorts = [
    {
        "select": "LastName",
        "order": "ascending"
    },
    {
        "select": "FirstName",
        "order": "ascending"
    },
    {
        "select": "MiddleName",
        "order": "ascending"
    }    
]

// call the function like this:
let sortedResults = sortResults(results, sorts)
0
задан Anand Undavia 18 January 2019 в 09:29
поделиться

2 ответа

Обычной практикой является использование Обещаний для этого. Вы можете создать вспомогательный Promise, который будет использовать requestAnimationFrame, и сделать ваш поток плоским и «доступным», добавив успешные обратные вызовы onResolve.

0
ответ дан Dima Vishnyakov 18 January 2019 в 09:29
поделиться

Да, вы действительно можете создавать функции, которые действуют как таймер: он возвращает обещание, которое разрешается, когда время истекает, что-то вроде этого:

timer = (duration) => {
  return new Promise(resolve => {
    window.setTimeout(resolve, duration);
  });
}

Аналогично, вы можете сделать то же самое для requestAnimationFrame. Хитрость заключается в том, чтобы использовать оператор распространения ES6, чтобы вы могли передавать произвольное количество аргументов в вызываемый обратный вызов:

animationFrame = (callback, ...args) => {
  return new Promise(resolve => {
    window.requestAnimationFrame(time => {
      callback(time, ...args);
    });
  })
}

Поскольку вы используете ES6, вы можете использовать функции async для ожидания таймер для завершения, прежде чем перейти к выполнению следующей строки кода. Если мы сломаем ваш код animationManager(), это можно увидеть следующим образом:

  1. Вы хотите начать с typingEffect
  2. Как только typingEffect будет завершено, вы захотите триггер deleteEffect

В этом случае мы можем реорганизовать ваш код следующим образом:

animationManager = () => {
  const deleteFunc = (time, typingData) => {
    this.deleteEffect(time, async () => {
      await this.timer(this.props.pauseBeforeRestarting);
      this.index = this.index === typingData.length - 1 ? 0 : this.index + 1;
      this.animationManager();
    });
  };

  const typeFunc = (time) => {
    const typingData = this.props.data;
    this.typeEffect(time, typingData[this.index], async () => {
      await this.timer(this.props.pauseBeforeDeleting);
      await this.animationFrame(deleteFunc, typingData);
    })
  };

  this.animationFrame(typeFunc);
};

Я разобрал ваш пример, чтобы предоставить подтверждение концепции переработанный код: https://codesandbox.io/s/308kxjzwrq

0
ответ дан Terry 18 January 2019 в 09:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: