Если вам интересна эта библиотека, добро пожаловать
StarИли рисоватьIssueОн также может стать участником этой библиотеки. (Если кто-то поможет перевести на английский или написать тест-кейс, буду признателен.
Если вы хотите перепечатать, просто прокомментируйте, а затем укажите источник и адрес github.
не отменятьPromise, но превращает несколько одинаковых промисов в один!Исполняемая функция все равно будет выполняться, и возвращаемое значение все равно будет, но она не будет генерировать лишниеPromise.
Пожалуйста, представьте следующие два сценария
1
Иногда на одной странице есть несколько разделов, как показано на изображении ниже.
И в этих частях есть дублирующиеся данные, такие как зеленая часть, они фактически запрашивают один и тот же контент на бэкэнде.
В это время, если мы возьмем запрос к каждому компонентному блоку модуля, очевидно, что три запроса, которые могут совместно использовать возвращаемое значение, повторяются.
Есть ли способ сделать для этих трех повторяющихся запросов только один запрос, а затем использовать одно и то же возвращаемое значение для всех трех запросов?
2
Предположим, есть компонент, обеспечивающий частичное обновление или загрузку.
Иногда, когда пользователь щелкает, чтобы обновить, из-за дрожания рук или по другим неизвестным причинам, короче говоря, он щелкает более одного раза, может быть, несколько раз, что приводит к прямой отправке нескольких запросов.
Можно ли для этих нескольких запросов интегрировать и отправить только один запрос?
once-init
Конечно, вы можете разработать сложную логику и инкапсулировать относительно безопасный компонент. В качестве альтернативы вы можете попробоватьonce-init?
Promise Function Init Once, Use Everywhere.
будет инициализирован только один разPromiseфункция.
будет выполняться при первом вызове объекта
PromiseФункция инициализируется, вызывается повторно, и повторная инициализация выполняться не будет.
тот самый
Promiseне будет выполняться дважды одновременно.
размер после сжатия
обещать
OnceInitупакованныйPromise Function, никогда не будет выполняться дважды одновременно.- если предыдущий
Promise FunctionСледующий вызывается без выполненияPromise Function, то следующийPromise Functionподелится предыдущимPromise FunctionизPromise.
Пример
Предположим, естьaxios Promiseзапрос, тип возвращаемого значенияnumber, значение777.
const requestNumber = async () => {
const res: AxiosResponse<number> = await axiosInstance.get("/api/number");
return res.data;
};
вы можете использоватьoiинкапсулировать этоPromiseфункция
const oiInstance = oi(requestNumber);
Теперь вы можете вызывать этот экземпляр где угодно.
init
Предположим, есть два методаfunctionAа такжеfunctionA, нужно отправить этот запрос.
async function functionA() {
...
const res = await oiInstance.init();
...
}
async function functionB() {
...
const res = await oiInstance.init();
...
}
И вам нужно использовать оба метода в определенном файле.
async function functionC() {
await functionA();
await functionB();
}
function functionD() {
functionA();
functionB();
}
дляfunctionC, существуетпервое исполнениеinitПозже,oiInstanceбудет сохранятьPromiseрезультат выполнения , а затем выполнитьinit,Будубольше не будет выдаватьсяPromiseпросить.
дляfunctionD,apiЗапрос будет отправлен только один раз,functionAа такжеfunctionBсерединаresбудет ждатьтот же запросВозвращаемое значение , не будет отправлять повторяющиеся запросы.
target
targetВозвращаемое значение может быть получено синхронно.
function functionE() {
...
const res = oiInstance.target;
...
}
если получитьtargetДо того, как инициализация завершена,targetценностьPromiseвозвращаемое значение, иначеtargetценностьundefined. Например,
const res = oiInstance.target; // undefined
await oiInstance.init();
const res = oiInstance.target; // [Return Value] 777
Обратите внимание, что пока выборка является синхронной,once-initвсе еще будет думать, что вам нужно сделать запрос в этот момент, поэтому позвонитеtargetСвойства также начнут инициализироваться.
В следующем примере мы предполагаемapiПродолжительность запроса составляет10s. В приведенном ниже примере запрос уже был сделан в первой строке.
const res = oiInstance.target; // undefined
/** Promise has been executed. */
setTimeout(async () => {
const resAfter = oiInstance.target; // [Return Value] 777
const intAffter = await oiInstance.init(); // [Return Value] 777 , Promise will not be executed again.
/** Since The Promise has been executed before, it will not be executed again. */
}, 10001);
и синхронно выполняется дважды одновременноinitто же самое, если получитьinitпосетил раньшеtargetсвойства, при доступеtargetвызванныйPromiseЕсли запрос не окончен,initбудет ждать непосредственно предыдущегоPromiseзакончить и вернуться к предыдущемуPromiseВозвращаемое значение.
Следующий пример поможет вам понять.
const res = oiInstance.target; // undefined
setTimeout(async () => {
const resAfter = oiInstance.target; // undefined
const intAffter = await oiInstance.init(); // [Return Value] 777
/** Since The Promise has been executing it will not be executing again. */
/** After About 8000ms, The Value will be return by the first promise done */
}, 2000);
здесьinitбудет ждать предыдущегоPromiseВозвращаемое значение выполнения функции, посколькуinitв200msвыполняется после этого, поэтому ему нужно только подождать800msВы можете получить это возвращаемое значение.
defaultValue
использоватьtargetСвойства обычно должны быть связаны со значениями по умолчанию, в то время какoiВторой параметр для васPromiseОпределите значения по умолчанию.
const defaultValue = -1;
const oiInstance = oi(requestNumber, defaultValue);
const ans = oiInstance.target; // -1
refresh
Если вы хотите обновить значение экземпляра, вам нужно позвонитьrefresh.
Предположим, что первое загруженное значение равно777, а значение после обновления равно888.
const ans = await oiInstance.init(); // [Retrun Value] 777
const ansAfterRefresh = await oiInstance.refresh(); // [Retrun Value] 888
После освежения звонитеinitа такжеtargetПриобретенное значение становится новым значением.
oiInstance.target; // undefined
await oiInstance.init(); // [Promise Retrun Value] 777
oiInstance.target; // 777
await oiInstance.refresh(); // [Promise Retrun Value] 888
/** Promise will not be exectued */
oiInstance.target; // 888
await oiInstance.init(); // 888
вы можете напрямую использоватьrefreshвыполнить инициализацию, при инициализации это иinitЭффект тот же.
oiInstance.target; // undefined
await oiInstance.refresh(); // [Promise Retrun Value] 777
oiInstance.target; // 777
await oiInstance.refresh(); // [Promise Retrun Value] 888
oiInstance.target; // 888
Если синхронизация вызывается дважды подрядrefresh,дваждыrefreshбудет ждатьтот же запросВозвращаемое значение , не будет отправлять повторяющиеся запросы.
async function functionA() {
console.log("A", await oiInstance.refresh());
}
async function functionB() {
console.log("B", await oiInstance.refresh());
}
functionA(); // 'A', [Promise Retrun Value] 777
functionB(); // 'B', [Promise Retrun Value] 777
/** only one promise is executed */
/** functionA and functionB share A same promise and promise return value */
мы все еще предполагаемapiЗапрашиваемая продолжительность10s === 10000ms.
oiInstance.refresh();
setTimeout(async () => {
await oiInstance.refresh();
}, 2000);
/** After 10000ms, two refresh will be exected at the same time */
Если асинхронно вызывается дваждыrefresh, затем отправьте запрос дважды.
async function functionA() {
console.log("A", await oiInstance.refresh());
}
async function functionB() {
console.log("B", await oiInstance.refresh());
}
await functionA(); // 'A', [Promise Retrun Value] 777
await functionB(); // 'B', [Promise Retrun Value] 888
/** Two different promises were executed */
Если вы считаете, что логика слишком сложна, пожалуйста, запомните хотя бы одну вещь,OnceInitупакованныйPromise Function, никогда не будет выполняться дважды одновременно.
Помимо,once-initтакже предоставляет другиеapi, чтобы удовлетворить больше потребностей, но выше его основные функции. Для получения дополнительной информации см.github для однократной инициализации.
HELP
Я также опубликуюVue3-Composition Apiверсия. (Запланированное)
export abstract class RefOnceInit<T, G = T> extends OnceInit<
Ref<T | undefined>,
G
> {
loading = ref<boolean>(false);
protected abstract factory(raw: G, observe: Ref<T | undefined>): void;
constructor(defaultValue?: T) {
const refed = ref<T>();
refed.value = defaultValue;
super(refed);
this.onLoading((event) => {
this.loading.value = event;
});
}
}
такRefOnceInitявляется отзывчивым объектом. оOnceInitСм. исходный код класса.
Когда запрос завершен, страница может быть запущенаUIИзменение.