Что происходит. Не пойму.
Есть метод жизненного цикла компонента в react-native
componentDidMount().
И есть такой код:
class EnterAdditionalData extends Component<Props> {
constructor(props) {
super(props);
this.state = {
isLoadInfo: false,
}
}
func = async () => {
for (let i = 0; i < 100000000; i++) {
console.log(i);
}
this.setState({isLoadtInfo: true});
}
componentDidMount() {
this.func();
}
render() {
return <View><Text>Hello</Text></View>
}
}
Итог: async не работает, т.к. выполняется цикл for (let i = 0; i < 100000000; i++) и соответственно все зависает пока работает цикл. На компоненте зависают все элементы управления. И где тут работа async если программа ждет выполнение метода помеченного async, а не продолжает параллельно выполняться?
А вот если вместо цикла мы указываем
setTimeout(() => {
this.setState({isLoadInfo: true});
}, 9000);
тогда все работает как надо:
class EnterAdditionalData extends Component<Props> {
constructor(props) {
super(props);
this.state = {
isLoadInfo: false,
}
}
func = async () => {
setTimeout(() => {
this.setState({isLoadInfo: true});
}, 9000);
}
componentDidMount() {
this.func();
}
render() {
return <View><Text>Hello</Text></View>
}
}
Здесь async работает как нужно. И программа не останавливается на методе setTimeout() и по прошествии 9 сек компонент рендерится
Что я делаю не так? Заранее спасибо.
Я нашел решение.
Т.к. JavaScript является однопоточным, то это значит что только один блок кода может запускаться за раз. Движок JS обрабатывает код строку за строкой и помещает все в стек, который у него один. Мы не можем использовать цикл без полной блокировки приложения. В данном случае наш цикл является блокирующим кодом, а точнее одним блоком кода.
Чтобы нам помочь JS разрулить эту ситуацию, нужно дать возможность обрабатывать цикл "порциями". А между этими "порциями" JS будет помещать остальной код (например: рендеринг, нажатие на различные элементы интерфейса и т.д.) в стек и выполнять его немедленно, а затем последует следующая "порция" нашего цикла. И так далее, пока не будет закончен весь цикл.
class EnterAdditionalData extends Component<Props> {
constructor(props) {
super(props);
this.state = {
isLoadInfo: false,
}
}
func = (count, chunksize, checksize, callback, callbackOther) => {
let i = 0;
(function chunk() {
let end = Math.min(i + chunksize, count);
for (; i < end; ++i) {
//Делать что-то во время цикла
callback.call(null, i);
}
if (i < count) {
//Делать что-то между циклами
if (i % checksize === 0) {
console.log(i);
callbackOther.call(null);
}
setTimeout(chunk, 0);
} else {
//То что выполнится после цикла
}
})();
};
setstate = () => {
if (!this.state.isLoadInfo)
this.setState({isLoadInfo: true});
};
componentDidMount() {
this.func(100000, 100, 10000,
(i) => {
//Делать что-то во время цикла
}, () => {
this.setstate();
});
}
render() {
return <View><Text>Hello</Text></View>
}
}
checksize - это кол-во итераций через которое будет выполнено ваше условие (в данном случае this.setstate())
P.S. Данный пример с циклом это всего лишь пример того, как долго могут выполняться некоторые участки кода, которые должны выполняться параллельно с остальным кодом. В случае если у вас есть участок кода к которому вы применяете async/await и в нем происходят долгие и сложные вычисления, можно использовать что-то вроде этого примера чтобы пользователи вашего приложения не заметили проблем при навигации по приложению.
И не забывайте очищать setTimeout() при размонтировании компонента в методе жизненного цикла компонента:
componentWillUnmount () {
}
Представленный пример кода отсюда (без моих доработок):
Как сделать неблокирующий код JavaScript?
Вот еще хорошая статья:
Создание неблокирующих функций в JavaScript
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
бот должен реагировать на команду /напомни действие в часы:минуты
Я получаю сообщение об ошибке полученной через GetLastError, и использую FormatMessage для преобразования в читабельный вид (для отладки)
Проект пустой, который создается по умолчанию (в формате qmake)
Нужно посчитать количество единичных бит, запрещается использовать любые арифметические операции (даже инкремент) и любые сторонние библиотеки...