#arrays #promise #push #svelte
Вопрос:
Я ломал голову над этой проблемой уже несколько часов, и хотя я нашел обходной путь для решения проблемы, я не могу смириться с тем фактом, что это вообще происходит. Я этого не понимаю. Похоже, существует какая-то проблема в использовании Array.push() в обработчике обещаний. Я создал приведенный ниже тестовый код, чтобы продемонстрировать его, и он воспроизводим в Svelte REPL. Я просто делаю что-то не так?
<script>
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo');
}, 300);
});
let itemsA = [];
let itemsB = [];
const addItem = (item) => {
itemsA[itemsA.length] = item;
itemsB.push(item);
}
const loadItems = (last) => {
addItem("Begin");
myPromise
.then((value) => {
addItem(value);
});
addItem("End");
return true;
};
loadItems();
</script>
<div>Items A: {itemsA}</div>
<div>Items B: {itemsB}</div>
Я бы подумал, что itemsB.push(item) должен делать то же самое, что и itemsA[itemsA.length] = item, и это так, за исключением случаев, когда он вызывается из обработчика обещаний.
Вместо этого я получаю следующие результаты:
Items A: Begin,End,foo
Items B: Begin,End
Правка: Я исключил обещания как источник странностей. Следующий код иллюстрирует это более просто.
<script>
let itemsA = [];
let itemsB = [];
const addItem = (item) => {
itemsA[itemsA.length] = item;
itemsB.push(item);
}
const clickHandler = () => {
addItem('click');
}
addItem('load');
</script>
<div>Items A: {itemsA}</div>
<div>Items B: {itemsB}</div>
<button on:click={clickHandler}>Click Me</button>
Комментарии:
1. Вот как работают обещания.
addItem
Во внешней области выполненияloadItems
выполняется передaddItem
внутренним обработчиком обещания. Для получения дополнительной информации здесь есть отличное видео: youtube.com/watch?v=8aGhZQkoFbQamp;ab_channel=JSConf
Ответ №1:
На самом деле это не имеет никакого отношения к обещанию. Когда вы добавляете кнопку и регистрируете массивы, вы видите, что » foo «также находится в «itemsB», он просто не отображается. Из стройных документов
Поскольку реактивность Svelte основана на назначениях, использование методов массива, таких как .push() и .splice (), не будет автоматически запускать обновления. Для запуска обновления требуется последующее назначение.
Соответствующий учебник
Вы можете использовать .push (), если за ним следует переназначение массива самому себе
itemsB.push(item);
itemsB = itemsB
или в качестве альтернативы используйте синтаксис оператора распространения
itemsB = [...itemsB, item]
Вот повторный вариант, чтобы попробовать это
Комментарии:
1. Это полезно, и я буду уверен, что не буду использовать push (я сам немного сузил его, как вы можете видеть из редактирования, которое я добавил, как раз когда вы добавляли этот ответ).. Хотя я не уверен, что понимаю, почему Стройность не делает этого. Разве не так?
2. Я не уверен, что понимаю, что ты имеешь в виду..? Вы имеете в виду, почему он не отображается просто с помощью .push()?
3. Да, именно это я и имею в виду.
4. Что ж, я думаю, мне придется передать этот вопрос создателям Svelte… 🙂 Я просто принял (на данный момент), что задание важно для того, чтобы все вело себя так, как ожидалось