#vue.js #vuex #s
Вопрос:
Недавно я заметил, что отправка определенного действия занимает намного больше времени, чем следовало бы, поэтому я решил добавить несколько таймеров.
Это код действия:
// ...
mutations: {
setPrimary(state, data) {
state.resources.primary = data
}
},
// ...
actions: {
async load({ commit }) {
const start = performance.now()
// ...
const apiResult = await apiClient.get("/")
const startCommit = performance.now()
commit("setPrimary", apiResult)
console.log(`commit finished in ${performance.now() - startCommit} ms`)
console.log(`action finished in ${performance.now() - start} ms`)
}
}
И код, отправляющий действие:
const start = performance.now()
await store.dispatch("load")
console.log(`dispatch finished in ${performance.now() - start} ms`)
Теперь ожидаемый результат будет заключаться в том, что тайминги довольно близки, но на самом деле все наоборот:
action finished in 820
dispatch finished in 1365 ms
Что для меня довольно запутанно, так как звонки dispatch
не должны добавлять такие огромные накладные расходы. До сих пор я понятия не имею, откуда это может взяться.
Редактировать:
Оказывается, это вызвано commit
звонком. Задержка не оправдывается и без этого. Время фиксации, подобное этому, показывает, что для выполнения требуется всего 1 мс, а это означает, что у этого каким-то образом есть побочные эффекты, о которых я не знаю.
Комментарии:
1. Активен ли Vue devtools? Можно ли это воспроизвести в производственном режиме? тело функции опущено для краткости — вот в чем проблема с вопросом. Если вы можете воспроизвести его без этого кода, сделайте это. В противном случае это актуально и не должно быть опущено.
2. @EstusFlask Vue devtools активен, но его можно воспроизвести в производственном режиме. Я не понимаю, почему код имеет значение, так как время происходит прямо за пределами
dispatch
вызова и прямо там, где начинается и заканчивается действие. Не должно быть такой существенной разницы, независимо от того, какой код выполняется между ними, если только с моей стороны не возникнет огромного недопонимания.3. Vue devtools должен быть неактивен по умолчанию в prod, не так ли? Попробуйте, чтобы Vue devtools были неактивны, чтобы вы были уверены, что они не вызывают замедления. Это важно, потому что неясно, оправдана ли задержка в 800 мс или имеет место какое-то глобальное замедление. Плагины Vuex могут вызвать задержку, или есть какой-то параллельный процесс, который занимает основной поток, включая визуализатор Vue. Я бы не ожидал, что в этом месте из ниоткуда возникнет 550 миль.
4. Я попробовал это с отключенными devtools, результат был похожим (меньшая задержка, но все равно примерно вдвое больше времени для выполнения
dispatch
. Чего я не могу понять, так это того, как может быть оправдана любая значительная задержка, поскольку оба таймера должны отсчитывать время выполнения действия. Поэтому, если что-то внутри действия происходит медленно, это также должно отображаться в результатах синхронизации внутри действия. Но, похоже, это не так.5. Я последовал вашему намеку на то, что это может быть что-то внутри действия, и оказывается, что есть определенный
commit
вызов, который вызывает эту задержку. Но я рассчитал время этого вызова, и он сообщает о времени выполнения всего 1 мс. Если я удалю этот вызов, не будет измеряться существенная задержка. Я все еще не вижу, как вызов функции, который выполняется за 1 мс, может вызвать задержку в 500 мс.
Ответ №1:
Накладные расходы возникают из-за того, что ваше действие является «асинхронной» функцией, что означает, что, когда «интерпретатор» выполняет его, он будет передавать его в «API браузера» для обработки его выполнения вместо того, чтобы выполнять его непосредственно в «Стеке», и ждать его результата, а затем вернет его обратно в «очередь», где «Цикл событий» будет ждать, пока стек опустеет, и вернет его с результатами в стек для продолжения выполнения