MOBILE-3988 core: Remove duplicated promise helper

main
Noel De Martin 2022-05-30 18:13:43 +02:00
parent b67d27fc0e
commit 6356623664
25 changed files with 162 additions and 201 deletions

View File

@ -321,17 +321,8 @@ export class AddonFilterMathJaxLoaderHandlerService extends CoreFilterDefaultHan
return;
}
const deferred = CoreUtils.promiseDefer<void>();
setTimeout(async () => {
try {
await this.waitForReady(retries + 1);
} finally {
deferred.resolve();
}
}, 250);
return deferred.promise;
await CoreUtils.wait(250);
await CoreUtils.ignoreErrors(this.waitForReady(retries + 1));
}
/**

View File

@ -888,18 +888,13 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
*
* @return Resolved when done.
*/
protected waitForFetch(): Promise<void> {
protected async waitForFetch(): Promise<void> {
if (!this.fetching) {
return Promise.resolve();
return;
}
const deferred = CoreUtils.promiseDefer<void>();
setTimeout(() => this.waitForFetch().finally(() => {
deferred.resolve();
}), 400);
return deferred.promise;
await CoreUtils.wait(400);
await CoreUtils.ignoreErrors(this.waitForFetch());
}
/**

View File

@ -15,8 +15,8 @@
import { BehaviorSubject, Subject } from 'rxjs';
import { CoreEvents } from '@singletons/events';
import { CoreDelegate, CoreDelegateDisplayHandler, CoreDelegateToDisplay } from './delegate';
import { CoreUtils } from '@services/utils/utils';
import { CoreSites } from '@services/sites';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Superclass to help creating sorted delegates.
@ -96,18 +96,17 @@ export class CoreSortedDelegate<
return this.sortedHandlers;
}
const deferred = CoreUtils.promiseDefer<DisplayType[]>();
const promisedHandlers = new CorePromisedValue<DisplayType[]>();
const subscription = this.getHandlersObservable().subscribe((handlers) => {
if (this.loaded) {
subscription?.unsubscribe();
// Return main handlers.
deferred.resolve(handlers);
promisedHandlers.resolve(handlers);
}
});
return deferred.promise;
return promisedHandlers;
}
/**

View File

@ -55,6 +55,13 @@ export class CorePromisedValue<T = unknown> extends CorePromise<T> {
this.rejectPromise = rejectPromise;
}
/**
* @deprecated since app 4.1. The instance can be directly used as a promise.
*/
get promise(): Promise<T> {
return this;
}
get value(): T | null {
return this.resolvedValue ?? null;
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Function to add to the queue.
@ -38,7 +38,7 @@ export type CoreQueueRunnerItem<T = any> = {
/**
* Deferred with a promise resolved/rejected with the result of the function.
*/
deferred: PromiseDefer<T>;
deferred: CorePromisedValue<T>;
};
/**
@ -122,7 +122,7 @@ export class CoreQueueRunner {
if (id in this.queue) {
if (!options.allowRepeated) {
// Item already in queue, return its promise.
return this.queue[id].deferred.promise;
return this.queue[id].deferred;
}
id = this.getUniqueId(id);
@ -132,7 +132,7 @@ export class CoreQueueRunner {
const item = {
id,
fn,
deferred: CoreUtils.promiseDefer<T>(),
deferred: new CorePromisedValue<T>(),
};
this.queue[id] = item;
@ -141,7 +141,7 @@ export class CoreQueueRunner {
// Process next item if we haven't reached the max yet.
this.processNextItem();
return item.deferred.promise;
return item.deferred;
}
}

View File

@ -32,7 +32,7 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUrlUtils, CoreUrlParams } from '@services/utils/url';
import { CoreUtils, CoreUtilsOpenInBrowserOptions, PromiseDefer } from '@services/utils/utils';
import { CoreUtils, CoreUtilsOpenInBrowserOptions } from '@services/utils/utils';
import { CoreConstants } from '@/core/constants';
import { SQLiteDB } from '@classes/sqlitedb';
import { CoreError } from '@classes/errors/error';
@ -46,6 +46,7 @@ import { asyncInstance, AsyncInstance } from '../utils/async-instance';
import { CoreDatabaseTable } from './database/database-table';
import { CoreDatabaseCachingStrategy } from './database/database-table-proxy';
import { CoreSilentError } from './errors/silenterror';
import { CorePromisedValue } from '@classes/promised-value';
/**
* QR Code type enumeration.
@ -779,7 +780,7 @@ export class CoreSite {
if (preSets.reusePending) {
const request = this.requestQueue.find((request) => request.cacheId == cacheId);
if (request) {
return request.deferred.promise;
return request.deferred;
}
}
@ -789,7 +790,7 @@ export class CoreSite {
data,
preSets,
wsPreSets,
deferred: CoreUtils.promiseDefer(),
deferred: new CorePromisedValue(),
};
return this.enqueueRequest(request);
@ -813,7 +814,7 @@ export class CoreSite {
);
}
return request.deferred.promise;
return request.deferred;
}
/**
@ -2291,7 +2292,7 @@ type RequestQueueItem<T = any> = {
data: any; // eslint-disable-line @typescript-eslint/no-explicit-any
preSets: CoreSiteWSPreSets;
wsPreSets: CoreWSPreSets;
deferred: PromiseDefer<T>;
deferred: CorePromisedValue<T>;
};
/**

View File

@ -33,6 +33,7 @@ import {
Type,
KeyValueDiffer,
} from '@angular/core';
import { CorePromisedValue } from '@classes/promised-value';
import { CoreCompile } from '@features/compile/services/compile';
import { CoreDomUtils } from '@services/utils/dom';
@ -278,14 +279,14 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
return this.pendingCalls[name].defer.promise;
}
const defer = CoreUtils.promiseDefer();
const defer = new CorePromisedValue();
this.pendingCalls[name] = {
params,
defer,
};
return defer.promise;
return defer;
}
}

View File

@ -154,6 +154,7 @@ import { ADDON_PRIVATEFILES_SERVICES } from '@addons/privatefiles/privatefiles.m
// Import some addon modules that define components, directives and pipes. Only import the important ones.
import { AddonModAssignComponentsModule } from '@addons/mod/assign/components/components.module';
import { AddonModWorkshopComponentsModule } from '@addons/mod/workshop/components/components.module';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
@ -352,6 +353,7 @@ export class CoreCompileProvider {
instance['CoreWindow'] = CoreWindow;
instance['CoreCache'] = CoreCache;
instance['CoreDelegate'] = CoreDelegate;
instance['CorePromisedValue'] = CorePromisedValue;
instance['CoreContentLinksHandlerBase'] = CoreContentLinksHandlerBase;
instance['CoreContentLinksModuleGradeHandler'] = CoreContentLinksModuleGradeHandler;
instance['CoreContentLinksModuleIndexHandler'] = CoreContentLinksModuleIndexHandler;

View File

@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
import { CoreDelegate, CoreDelegateHandler, CoreDelegateToDisplay } from '@classes/delegate';
import { CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreUtils } from '@services/utils/utils';
import {
CoreCourseAnyCourseData,
CoreCourseAnyCourseDataWithOptions,
@ -28,6 +28,7 @@ import { CoreCourseProvider } from './course';
import { Params } from '@angular/router';
import { makeSingleton } from '@singletons';
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Interface that all course options handlers must implement.
@ -224,7 +225,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate<CoreCourseOpt
access: CoreCourseAccess;
navOptions?: CoreCourseUserAdminOrNavOptionIndexed;
admOptions?: CoreCourseUserAdminOrNavOptionIndexed;
deferred: PromiseDefer<void>;
deferred: CorePromisedValue<void>;
enabledHandlers: CoreCourseOptionsHandler[];
enabledMenuHandlers: CoreCourseOptionsMenuHandler[];
};
@ -331,7 +332,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate<CoreCourseOpt
access: accessData,
navOptions,
admOptions,
deferred: CoreUtils.promiseDefer(),
deferred: new CorePromisedValue(),
enabledHandlers: [],
enabledMenuHandlers: [],
};
@ -339,13 +340,13 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate<CoreCourseOpt
this.coursesHandlers[courseId].access = accessData;
this.coursesHandlers[courseId].navOptions = navOptions;
this.coursesHandlers[courseId].admOptions = admOptions;
this.coursesHandlers[courseId].deferred = CoreUtils.promiseDefer();
this.coursesHandlers[courseId].deferred = new CorePromisedValue();
}
this.updateHandlersForCourse(courseId, accessData, navOptions, admOptions);
}
await this.coursesHandlers[courseId].deferred.promise;
await this.coursesHandlers[courseId].deferred;
return this.coursesHandlers[courseId].enabledHandlers;
}

View File

@ -1304,16 +1304,15 @@ export class CoreCourseProvider {
}
// Wait for plugins to be loaded.
const deferred = CoreUtils.promiseDefer<void>();
await new Promise((resolve, reject) => {
const observer = CoreEvents.on(CoreEvents.SITE_PLUGINS_LOADED, () => {
observer?.off();
CoreCourseFormatDelegate.openCourse(<CoreCourseAnyCourseData> course, navOptions)
.then(deferred.resolve).catch(deferred.reject);
CoreCourseFormatDelegate.openCourse(<CoreCourseAnyCourseData> course, navOptions).then(resolve).catch(reject);
});
});
return deferred.promise;
return;
} catch (error) {
// The site plugin failed to load. The user needs to restart the app to try loading it again.
const message = Translate.instant('core.courses.errorloadplugins');

View File

@ -24,7 +24,7 @@ import { CoreFile, CoreFileProvider, CoreFileProgressEvent } from '@services/fil
import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate, Camera, Chooser, Platform, ActionSheetController } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { CoreCanceledError } from '@classes/errors/cancelederror';
@ -36,6 +36,7 @@ import { CoreIonLoadingElement } from '@classes/ion-loading';
import { CoreWSUploadFileResult } from '@services/ws';
import { CoreSites } from '@services/sites';
import { CoreText } from '@singletons/text';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Helper service to upload files.
@ -44,7 +45,7 @@ import { CoreText } from '@singletons/text';
export class CoreFileUploaderHelperProvider {
protected logger: CoreLogger;
protected filePickerDeferred?: PromiseDefer<CoreWSUploadFileResult | FileEntry>;
protected filePickerDeferred?: CorePromisedValue<CoreWSUploadFileResult | FileEntry>;
protected actionSheet?: HTMLIonActionSheetElement;
constructor() {
@ -349,7 +350,7 @@ export class CoreFileUploaderHelperProvider {
}];
const handlers = CoreFileUploaderDelegate.getHandlers(mimetypes);
this.filePickerDeferred = CoreUtils.promiseDefer();
this.filePickerDeferred = new CorePromisedValue();
// Create a button for each handler.
handlers.forEach((handler) => {
@ -431,7 +432,7 @@ export class CoreFileUploaderHelperProvider {
});
}, 500);
return this.filePickerDeferred.promise;
return this.filePickerDeferred;
}
/**

View File

@ -1288,10 +1288,8 @@ export class CoreLoginHelperProvider {
*
* @return Promise resolved if the user accepts to scan QR.
*/
showScanQRInstructions(): Promise<void> {
const deferred = CoreUtils.promiseDefer<void>();
// Show some instructions first.
async showScanQRInstructions(): Promise<void> {
await new Promise<void>((resolve, reject) => {
CoreDomUtils.showAlertWithOptions({
header: Translate.instant('core.login.faqwhereisqrcode'),
message: Translate.instant(
@ -1302,20 +1300,15 @@ export class CoreLoginHelperProvider {
{
text: Translate.instant('core.cancel'),
role: 'cancel',
handler: (): void => {
deferred.reject(new CoreCanceledError());
},
handler: () => reject(new CoreCanceledError()),
},
{
text: Translate.instant('core.next'),
handler: (): void => {
deferred.resolve();
},
handler: () => resolve(),
},
],
});
return deferred.promise;
});
}
/**

View File

@ -256,14 +256,13 @@ export class CorePushNotificationsProvider {
return;
}
const deferred = CoreUtils.promiseDefer<void>();
win.PushNotification.enableAnalytics(deferred.resolve, (error) => {
await new Promise<void>(resolve => {
win.PushNotification.enableAnalytics(resolve, (error) => {
this.logger.error('Error enabling or disabling Firebase analytics', enable, error);
deferred.resolve();
}, !!enable);
await deferred.promise;
resolve();
}, !!enable);
});
}
/**
@ -357,14 +356,12 @@ export class CorePushNotificationsProvider {
return;
}
const deferred = CoreUtils.promiseDefer<void>();
win.PushNotification.logEvent(deferred.resolve, (error) => {
await new Promise<void>(resolve => {
win.PushNotification.logEvent(resolve, (error) => {
this.logger.error('Error logging firebase event', name, error);
deferred.resolve();
resolve();
}, name, data, !!filter);
await deferred.promise;
});
}
/**

View File

@ -27,8 +27,8 @@ import {
CoreSitePluginsCourseOptionHandlerData,
CoreSitePluginsPlugin,
} from '@features/siteplugins/services/siteplugins';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreSitePluginsBaseHandler } from './base-handler';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Handler to display a site plugin in course options.
@ -38,7 +38,7 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl
priority: number;
isMenuHandler: boolean;
protected updatingDefer?: PromiseDefer<void>;
protected updatingDefer?: CorePromisedValue<void>;
constructor(
name: string,
@ -59,7 +59,7 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl
async isEnabledForCourse(courseId: number): Promise<boolean> {
// Wait for "init" result to be updated.
if (this.updatingDefer) {
await this.updatingDefer.promise;
await this.updatingDefer;
}
return CoreSitePlugins.isHandlerEnabledForCourse(
@ -132,7 +132,7 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl
* Mark init being updated.
*/
updatingInit(): void {
this.updatingDefer = CoreUtils.promiseDefer();
this.updatingDefer = new CorePromisedValue();
}
}

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CorePromisedValue } from '@classes/promised-value';
import {
CoreSitePlugins,
CoreSitePluginsContent,
@ -26,7 +27,6 @@ import {
CoreUserProfileHandlerData,
} from '@features/user/services/user-delegate';
import { CoreNavigator } from '@services/navigator';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { Md5 } from 'ts-md5';
import { CoreSitePluginsBaseHandler } from './base-handler';
@ -38,7 +38,7 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle
priority: number;
type: string;
protected updatingDefer?: PromiseDefer<void>;
protected updatingDefer?: CorePromisedValue<void>;
constructor(
name: string,
@ -130,7 +130,7 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle
* Mark init being updated.
*/
updatingInit(): void {
this.updatingDefer = CoreUtils.promiseDefer();
this.updatingDefer = new CorePromisedValue();
}
}

View File

@ -23,12 +23,13 @@ import { CoreFilepool } from '@services/filepool';
import { CoreLang } from '@services/lang';
import { CoreSites } from '@services/sites';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreUtils } from '@services/utils/utils';
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { CoreLogger } from '@singletons/logger';
import { CoreSitePluginsModuleHandler } from '../classes/handlers/module-handler';
import { CorePromisedValue } from '@classes/promised-value';
const ROOT_CACHE_KEY = 'CoreSitePlugins:';
@ -44,7 +45,7 @@ export class CoreSitePluginsProvider {
protected logger: CoreLogger;
protected sitePlugins: {[name: string]: CoreSitePluginsHandler} = {}; // Site plugins registered.
protected sitePluginPromises: {[name: string]: Promise<void>} = {}; // Promises of loading plugins.
protected fetchPluginsDeferred: PromiseDefer<void>;
protected fetchPluginsDeferred: CorePromisedValue<void>;
protected moduleHandlerInstances: Record<string, CoreSitePluginsModuleHandler> = {};
hasSitePluginsLoaded = false;
@ -59,9 +60,9 @@ export class CoreSitePluginsProvider {
});
// Initialize deferred at start and on logout.
this.fetchPluginsDeferred = CoreUtils.promiseDefer();
this.fetchPluginsDeferred = new CorePromisedValue();
CoreEvents.on(CoreEvents.LOGOUT, () => {
this.fetchPluginsDeferred = CoreUtils.promiseDefer();
this.fetchPluginsDeferred = new CorePromisedValue();
});
}
@ -659,8 +660,8 @@ export class CoreSitePluginsProvider {
*
* @return Promise resolved when site plugins have been fetched.
*/
waitFetchPlugins(): Promise<void> {
return this.fetchPluginsDeferred.promise;
async waitFetchPlugins(): Promise<void> {
await this.fetchPluginsDeferred;
}
/**

View File

@ -16,7 +16,6 @@ import { Injectable } from '@angular/core';
import { CoreDB } from '@services/db';
import { CoreEvents } from '@singletons/events';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb';
import { makeSingleton, Keyboard, Network, StatusBar, Platform, Device } from '@singletons';
@ -28,6 +27,8 @@ import { CoreRedirectPayload } from './navigator';
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
import { asyncInstance } from '../utils/async-instance';
import { CoreDatabaseTable } from '@classes/database/database-table';
import { CorePromisedValue } from '@classes/promised-value';
import { Subscription } from 'rxjs';
/**
* Factory to provide some global functionalities, like access to the global app database.
@ -47,7 +48,7 @@ export class CoreAppProvider {
protected db?: SQLiteDB;
protected logger: CoreLogger;
protected ssoAuthenticationDeferred?: PromiseDefer<void>;
protected ssoAuthenticationDeferred?: CorePromisedValue<void>;
protected isKeyboardShown = false;
protected keyboardOpening = false;
protected keyboardClosing = false;
@ -451,14 +452,14 @@ export class CoreAppProvider {
* NOT when the browser is opened.
*/
startSSOAuthentication(): void {
this.ssoAuthenticationDeferred = CoreUtils.promiseDefer<void>();
this.ssoAuthenticationDeferred = new CorePromisedValue();
// Resolve it automatically after 10 seconds (it should never take that long).
const cancelTimeout = setTimeout(() => this.finishSSOAuthentication(), 10000);
// If the promise is resolved because finishSSOAuthentication is called, stop the cancel promise.
// eslint-disable-next-line promise/catch-or-return
this.ssoAuthenticationDeferred.promise.then(() => clearTimeout(cancelTimeout));
this.ssoAuthenticationDeferred.then(() => clearTimeout(cancelTimeout));
}
/**
@ -486,9 +487,7 @@ export class CoreAppProvider {
* @return Promise resolved once SSO authentication finishes.
*/
async waitForSSOAuthentication(): Promise<void> {
const promise = this.ssoAuthenticationDeferred?.promise;
await promise;
await this.ssoAuthenticationDeferred;
}
/**
@ -497,7 +496,9 @@ export class CoreAppProvider {
* @param timeout Maximum time to wait, use null to wait forever.
*/
async waitForResume(timeout: number | null = null): Promise<void> {
let deferred: PromiseDefer<void> | null = CoreUtils.promiseDefer<void>();
let deferred: CorePromisedValue<void> | null = new CorePromisedValue();
let resumeSubscription: Subscription | null = null;
let timeoutId: number | null = null;
const stopWaiting = () => {
if (!deferred) {
@ -505,16 +506,16 @@ export class CoreAppProvider {
}
deferred.resolve();
resumeSubscription.unsubscribe();
resumeSubscription?.unsubscribe();
timeoutId && clearTimeout(timeoutId);
deferred = null;
};
const resumeSubscription = Platform.resume.subscribe(stopWaiting);
const timeoutId = timeout ? setTimeout(stopWaiting, timeout) : false;
resumeSubscription = Platform.resume.subscribe(stopWaiting);
timeoutId = timeout ? window.setTimeout(stopWaiting, timeout) : null;
await deferred.promise;
await deferred;
}
/**

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CorePromisedValue } from '@classes/promised-value';
import { CoreAppSchema } from '@services/app';
import { PromiseDefer } from '@services/utils/utils';
/**
* Database variables for CoreLocalNotifications service.
@ -76,5 +76,5 @@ export const APP_SCHEMA: CoreAppSchema = {
export type CodeRequestsQueueItem = {
table: string;
id: string;
deferreds: PromiseDefer<number>[];
deferreds: CorePromisedValue<number>[];
};

View File

@ -26,7 +26,7 @@ import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTextUtils } from '@services/utils/text';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUrlUtils } from '@services/utils/url';
import { CoreUtils, CoreUtilsOpenFileOptions, PromiseDefer } from '@services/utils/utils';
import { CoreUtils, CoreUtilsOpenFileOptions } from '@services/utils/utils';
import { SQLiteDB } from '@classes/sqlitedb';
import { CoreError } from '@classes/errors/error';
import { CoreConstants } from '@/core/constants';
@ -53,6 +53,7 @@ import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/da
import { lazyMap, LazyMap } from '../utils/lazy-map';
import { asyncInstance, AsyncInstance } from '../utils/async-instance';
import { CoreText } from '@singletons/text';
import { CorePromisedValue } from '@classes/promised-value';
/*
* Factory for handling downloading files and retrieve downloaded files.
@ -94,7 +95,7 @@ export class CoreFilepoolProvider {
];
// To handle file downloads using the queue.
protected queueDeferreds: { [s: string]: { [s: string]: CoreFilepoolPromiseDefer } } = {};
protected queueDeferreds: { [s: string]: { [s: string]: CoreFilepoolPromisedValue } } = {};
protected sizeCache: {[fileUrl: string]: number} = {}; // A "cache" to store file sizes.
// Variables to prevent downloading packages/files twice at the same time.
protected packagesPromises: { [s: string]: { [s: string]: Promise<void> } } = {};
@ -450,7 +451,7 @@ export class CoreFilepoolProvider {
this.logger.debug(`File ${fileId} already in queue and does not require update`);
if (queueDeferred) {
// If we were able to retrieve the queue deferred before, we use that one.
return queueDeferred.promise;
return queueDeferred;
} else {
// Create a new deferred and return its promise.
return this.getQueuePromise(siteId, fileId, true, onProgress);
@ -1889,7 +1890,7 @@ export class CoreFilepoolProvider {
fileId: string,
create: boolean = true,
onProgress?: CoreFilepoolOnProgressCallback,
): CoreFilepoolPromiseDefer | undefined {
): CoreFilepoolPromisedValue | undefined {
if (!this.queueDeferreds[siteId]) {
if (!create) {
return;
@ -1900,7 +1901,7 @@ export class CoreFilepoolProvider {
if (!create) {
return;
}
this.queueDeferreds[siteId][fileId] = CoreUtils.promiseDefer();
this.queueDeferreds[siteId][fileId] = new CorePromisedValue();
}
if (onProgress) {
@ -1938,9 +1939,7 @@ export class CoreFilepoolProvider {
create: boolean = true,
onProgress?: CoreFilepoolOnProgressCallback,
): Promise<void> | undefined {
const deferred = this.getQueueDeferred(siteId, fileId, create, onProgress);
return deferred?.promise;
return this.getQueueDeferred(siteId, fileId, create, onProgress);
}
/**
@ -3032,11 +3031,11 @@ export class CoreFilepoolProvider {
* @param error String identifier for error message, if rejected.
*/
protected treatQueueDeferred(siteId: string, fileId: string, resolve: boolean, error?: string): void {
if (this.queueDeferreds[siteId] && this.queueDeferreds[siteId][fileId]) {
if (siteId in this.queueDeferreds && fileId in this.queueDeferreds[siteId]) {
if (resolve) {
this.queueDeferreds[siteId][fileId].resolve();
} else {
this.queueDeferreds[siteId][fileId].reject(error);
this.queueDeferreds[siteId][fileId].reject(new Error(error));
}
delete this.queueDeferreds[siteId][fileId];
}
@ -3138,7 +3137,7 @@ export type CoreFilepoolOnProgressCallback<T = unknown> = (event: T) => void;
/**
* Deferred promise for file pool. It's similar to the result of $q.defer() in AngularJS.
*/
type CoreFilepoolPromiseDefer = PromiseDefer<void> & {
type CoreFilepoolPromisedValue = CorePromisedValue<void> & {
onProgress?: CoreFilepoolOnProgressCallback; // On Progress function.
};

View File

@ -20,7 +20,6 @@ import { CoreApp } from '@services/app';
import { CoreConfig } from '@services/config';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { SQLiteDB } from '@classes/sqlitedb';
import { CoreQueueRunner } from '@classes/queue-runner';
import { CoreError } from '@classes/errors/error';
@ -34,6 +33,7 @@ import {
SITES_TABLE_NAME,
CodeRequestsQueueItem,
} from '@services/database/local-notifications';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Service to handle local notifications.
@ -507,7 +507,7 @@ export class CoreLocalNotificationsProvider {
* @return Promise resolved when the code is retrieved.
*/
protected requestCode(table: string, id: string): Promise<number> {
const deferred = CoreUtils.promiseDefer<number>();
const deferred = new CorePromisedValue<number>();
const key = table + '#' + id;
const isQueueEmpty = Object.keys(this.codeRequestsQueue).length == 0;
@ -527,7 +527,7 @@ export class CoreLocalNotificationsProvider {
this.processNextRequest();
}
return deferred.promise;
return deferred;
}
/**

View File

@ -21,9 +21,10 @@ import { makeSingleton } from '@singletons';
import { CoreH5P } from '@features/h5p/services/h5p';
import { CoreLoginHelper } from '@features/login/services/login-helper';
import { CoreSites } from './sites';
import { CoreUtils, PromiseDefer } from './utils/utils';
import { CoreUtils } from './utils/utils';
import { CoreApp } from './app';
import { CoreZoomLevel } from '@features/settings/services/settings-helper';
import { CorePromisedValue } from '@classes/promised-value';
const VERSION_APPLIED = 'version_applied';
@ -36,11 +37,11 @@ const VERSION_APPLIED = 'version_applied';
export class CoreUpdateManagerProvider {
protected logger: CoreLogger;
protected doneDeferred: PromiseDefer<void>;
protected doneDeferred: CorePromisedValue<void>;
constructor() {
this.logger = CoreLogger.getInstance('CoreUpdateManagerProvider');
this.doneDeferred = CoreUtils.promiseDefer();
this.doneDeferred = new CorePromisedValue();
}
/**
@ -49,7 +50,7 @@ export class CoreUpdateManagerProvider {
* @return Promise resolved when the load function is done.
*/
get donePromise(): Promise<void> {
return this.doneDeferred.promise;
return this.doneDeferred;
}
/**

View File

@ -678,30 +678,29 @@ export class CoreDomUtilsProvider {
* Wait an element to exists using the findFunction.
*
* @param findFunction The function used to find the element.
* @param retries Number of retries before giving up.
* @param retryAfter Milliseconds to wait before retrying if the element wasn't found.
* @return Resolved if found, rejected if too many tries.
* @deprecated since app 4.0 Use CoreDom.waitToBeInsideElement instead.
*/
waitElementToExist(findFunction: () => HTMLElement | null): Promise<HTMLElement> {
const promiseInterval = CoreUtils.promiseDefer<HTMLElement>();
let tries = 100;
async waitElementToExist(
findFunction: () => HTMLElement | null,
retries: number = 100,
retryAfter: number = 100,
): Promise<HTMLElement> {
const element = findFunction();
const clear = setInterval(() => {
const element: HTMLElement | null = findFunction();
if (element) {
clearInterval(clear);
promiseInterval.resolve(element);
} else {
tries--;
if (tries <= 0) {
clearInterval(clear);
promiseInterval.reject();
if (!element && retries === 0) {
throw Error('Element not found');
}
}
}, 100);
return promiseInterval.promise;
if (!element) {
await CoreUtils.wait(retryAfter);
return this.waitElementToExist(findFunction, retries - 1);
}
return element;
}
/**

View File

@ -22,7 +22,7 @@ import { CoreFileHelper } from '@services/file-helper';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrlUtils } from '@services/utils/url';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Network, NgZone, Translate, Diagnostic } from '@singletons';
import { CoreLogger } from '@singletons/logger';
@ -30,6 +30,7 @@ import { CoreUrl } from '@singletons/url';
import { CoreWindow } from '@singletons/window';
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
import { CoreText } from '@singletons/text';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Possible types of frame elements.
@ -48,7 +49,7 @@ export class CoreIframeUtilsProvider {
static readonly FRAME_TAGS = ['iframe', 'frame', 'object', 'embed'];
protected logger: CoreLogger;
protected waitAutoLoginDefer?: PromiseDefer<void>;
protected waitAutoLoginDefer?: CorePromisedValue<void>;
constructor() {
this.logger = CoreLogger.getInstance('CoreIframeUtilsProvider');
@ -193,14 +194,14 @@ export class CoreIframeUtilsProvider {
if (this.waitAutoLoginDefer) {
// Another iframe is already using auto-login. Wait for it to finish.
await this.waitAutoLoginDefer.promise;
await this.waitAutoLoginDefer;
// Return the original URL, we can't request a new auto-login.
return url;
}
// First iframe requesting auto-login.
this.waitAutoLoginDefer = CoreUtils.promiseDefer();
this.waitAutoLoginDefer = new CorePromisedValue();
const finalUrl = await currentSite.getAutoLoginUrl(url, false);

View File

@ -34,6 +34,7 @@ import { CoreFileEntry } from '@services/file-helper';
import { CoreConstants } from '@/core/constants';
import { CoreWindow } from '@singletons/window';
import { CoreColors } from '@singletons/colors';
import { CorePromisedValue } from '@classes/promised-value';
type TreeNode<T> = T & { children: TreeNode<T>[] };
@ -48,7 +49,7 @@ export class CoreUtilsProvider {
protected logger: CoreLogger;
protected iabInstance?: InAppBrowserObject;
protected uniqueIds: {[name: string]: number} = {};
protected qrScanData?: {deferred: PromiseDefer<string>; observable: Subscription};
protected qrScanData?: {deferred: CorePromisedValue<string>; observable: Subscription};
protected initialColorSchemeContent = 'light dark';
constructor() {
@ -1325,18 +1326,13 @@ export class CoreUtilsProvider {
}
/**
* Similar to AngularJS $q.defer().
* Create a deferred promise that can be resolved or rejected explicitly.
*
* @return The deferred promise.
* @deprecated since app 4.1. Use CorePromisedValue instead.
*/
promiseDefer<T>(): PromiseDefer<T> {
const deferred: Partial<PromiseDefer<T>> = {};
deferred.promise = new Promise((resolve, reject): void => {
deferred.resolve = resolve as (value?: T | undefined) => void;
deferred.reject = reject;
});
return deferred as PromiseDefer<T>;
promiseDefer<T>(): CorePromisedValue<T> {
return new CorePromisedValue<T>();
}
/**
@ -1635,12 +1631,12 @@ export class CoreUtilsProvider {
if (this.qrScanData && this.qrScanData.deferred) {
// Already scanning.
return this.qrScanData.deferred.promise;
return this.qrScanData.deferred;
}
// Start scanning.
this.qrScanData = {
deferred: this.promiseDefer(),
deferred: new CorePromisedValue(),
// When text is received, stop scanning and return the text.
observable: QRScanner.scan().subscribe(text => this.stopScanQR(text, false)),
@ -1659,7 +1655,7 @@ export class CoreUtilsProvider {
colorSchemeMeta.setAttribute('content', 'normal');
}
return this.qrScanData.deferred.promise;
return this.qrScanData.deferred;
} catch (e) {
this.stopScanQR(e, true);
@ -1697,7 +1693,7 @@ export class CoreUtilsProvider {
this.qrScanData.observable.unsubscribe(); // Stop scanning.
if (error) {
this.qrScanData.deferred.reject(data);
this.qrScanData.deferred.reject(typeof data === 'string' ? new Error(data) : data);
} else if (data !== undefined) {
this.qrScanData.deferred.resolve(data as string);
} else {
@ -1769,30 +1765,6 @@ export class CoreUtilsProvider {
export const CoreUtils = makeSingleton(CoreUtilsProvider);
/**
* Deferred promise. It's similar to the result of $q.defer() in AngularJS.
*/
export type PromiseDefer<T> = {
/**
* The promise.
*/
promise: Promise<T>;
/**
* Function to resolve the promise.
*
* @param value The resolve value.
*/
resolve: (value?: T) => void; // Function to resolve the promise.
/**
* Function to reject the promise.
*
* @param reason The reject param.
*/
reject: (reason?: unknown) => void;
};
/**
* Data for each entry of executeOrderedPromises.
*/

View File

@ -26,7 +26,6 @@ import { CoreApp } from '@services/app';
import { CoreFile, CoreFileFormat } from '@services/file';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTextErrorObject, CoreTextUtils } from '@services/utils/text';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreConstants } from '@/core/constants';
import { CoreError } from '@classes/errors/error';
import { CoreInterceptor } from '@classes/interceptor';
@ -38,6 +37,7 @@ import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreSite } from '@classes/site';
import { CoreHttpError } from '@classes/errors/httperror';
import { CorePromisedValue } from '@classes/promised-value';
/**
* This service allows performing WS calls and download/upload files.
@ -76,12 +76,12 @@ export class CoreWSProvider {
siteUrl,
data,
preSets,
deferred: CoreUtils.promiseDefer<T>(),
deferred: new CorePromisedValue<T>(),
};
this.retryCalls.push(call);
return call.deferred.promise;
return call.deferred;
}
/**
@ -1363,7 +1363,7 @@ type RetryCall = {
siteUrl: string;
data: Record<string, unknown>;
preSets: CoreWSPreSets;
deferred: PromiseDefer<unknown>;
deferred: CorePromisedValue;
};
/**