MOBILE-2272 quiz: Convert sync function to async/await

main
Dani Palou 2020-09-29 15:06:31 +02:00
parent 46efcc441a
commit 9d0ae3c34b
1 changed files with 100 additions and 108 deletions

View File

@ -21,6 +21,7 @@ import { CoreSitesProvider, CoreSitesReadingStrategy } from '@providers/sites';
import { CoreSyncProvider } from '@providers/sync'; import { CoreSyncProvider } from '@providers/sync';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { CoreUtils } from '@providers/utils/utils';
import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
@ -288,16 +289,6 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
syncQuiz(quiz: any, askPreflight?: boolean, siteId?: string): Promise<AddonModQuizSyncResult> { syncQuiz(quiz: any, askPreflight?: boolean, siteId?: string): Promise<AddonModQuizSyncResult> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
const warnings = [];
const courseId = quiz.course;
const modOptions = {
cmId: quiz.coursemodule,
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
siteId,
};
let syncPromise;
let preflightData;
if (this.isSyncing(quiz.id, siteId)) { if (this.isSyncing(quiz.id, siteId)) {
// There's already a sync ongoing for this quiz, return the promise. // There's already a sync ongoing for this quiz, return the promise.
return this.getOngoingSync(quiz.id, siteId); return this.getOngoingSync(quiz.id, siteId);
@ -310,83 +301,95 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
return Promise.reject(this.translate.instant('core.errorsyncblocked', {$a: this.componentTranslate})); return Promise.reject(this.translate.instant('core.errorsyncblocked', {$a: this.componentTranslate}));
} }
return this.addOngoingSync(quiz.id, this.performSyncQuiz(quiz, askPreflight, siteId), siteId);
}
/**
* Perform the quiz sync.
*
* @param quiz Quiz.
* @param askPreflight Whether we should ask for preflight data if needed.
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved in success.
*/
async performSyncQuiz(quiz: any, askPreflight?: boolean, siteId?: string): Promise<AddonModQuizSyncResult> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
const warnings = [];
const courseId = quiz.course;
const modOptions = {
cmId: quiz.coursemodule,
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
siteId,
};
this.logger.debug('Try to sync quiz ' + quiz.id + ' in site ' + siteId); this.logger.debug('Try to sync quiz ' + quiz.id + ' in site ' + siteId);
// Sync offline logs. // Sync offline logs.
syncPromise = this.logHelper.syncIfNeeded(AddonModQuizProvider.COMPONENT, quiz.id, siteId).catch(() => { await CoreUtils.instance.ignoreErrors(this.logHelper.syncIfNeeded(AddonModQuizProvider.COMPONENT, quiz.id, siteId));
// Ignore errors.
}).then(() => { // Get all the offline attempts for the quiz. It should always be 0 or 1 attempt
// Get all the offline attempts for the quiz. const offlineAttempts = await this.quizOfflineProvider.getQuizAttempts(quiz.id, siteId);
return this.quizOfflineProvider.getQuizAttempts(quiz.id, siteId);
}).then((attempts) => { if (!offlineAttempts.length) {
// Should return 0 or 1 attempt. // Nothing to sync, finish.
if (!attempts.length) {
return this.finishSync(siteId, quiz, courseId, warnings); return this.finishSync(siteId, quiz, courseId, warnings);
} }
const offlineAttempt = attempts.pop(); if (!this.appProvider.isOnline()) {
// Cannot sync in offline.
throw new Error(this.translate.instant('core.cannotconnect'));
}
const offlineAttempt = offlineAttempts.pop();
// Now get the list of online attempts to make sure this attempt exists and isn't finished. // Now get the list of online attempts to make sure this attempt exists and isn't finished.
return this.quizProvider.getUserAttempts(quiz.id, modOptions).then((attempts) => { const onlineAttempts = await this.quizProvider.getUserAttempts(quiz.id, modOptions);
const lastAttemptId = attempts.length ? attempts[attempts.length - 1].id : undefined;
let onlineAttempt;
// Search the attempt we retrieved from offline. const lastAttemptId = onlineAttempts.length ? onlineAttempts[onlineAttempts.length - 1].id : undefined;
for (const i in attempts) { const onlineAttempt = onlineAttempts.find((attempt) => {
const attempt = attempts[i]; return attempt.id == offlineAttempt.id;
});
if (attempt.id == offlineAttempt.id) {
onlineAttempt = attempt;
break;
}
}
if (!onlineAttempt || this.quizProvider.isAttemptFinished(onlineAttempt.state)) { if (!onlineAttempt || this.quizProvider.isAttemptFinished(onlineAttempt.state)) {
// Attempt not found or it's finished in online. Discard it. // Attempt not found or it's finished in online. Discard it.
warnings.push(this.translate.instant('addon.mod_quiz.warningattemptfinished')); warnings.push(this.translate.instant('addon.mod_quiz.warningattemptfinished'));
return this.finishSync(siteId, quiz, courseId, warnings, offlineAttempt.id, offlineAttempt, onlineAttempt, return this.finishSync(siteId, quiz, courseId, warnings, offlineAttempt.id, offlineAttempt, onlineAttempt, true);
true);
} }
// Get the data stored in offline. // Get the data stored in offline.
return this.quizOfflineProvider.getAttemptAnswers(offlineAttempt.id, siteId).then((answersList) => { const answersList = await this.quizOfflineProvider.getAttemptAnswers(offlineAttempt.id, siteId);
if (!answersList.length) { if (!answersList.length) {
// No answers stored, finish. // No answers stored, finish.
return this.finishSync(siteId, quiz, courseId, warnings, lastAttemptId, offlineAttempt, onlineAttempt, return this.finishSync(siteId, quiz, courseId, warnings, lastAttemptId, offlineAttempt, onlineAttempt, true);
true);
} }
const answers = this.questionProvider.convertAnswersArrayToObject(answersList), const offlineAnswers = this.questionProvider.convertAnswersArrayToObject(answersList);
offlineQuestions = this.quizOfflineProvider.classifyAnswersInQuestions(answers); const offlineQuestions = this.quizOfflineProvider.classifyAnswersInQuestions(offlineAnswers);
let finish;
// We're going to need preflightData, get it. // We're going to need preflightData, get it.
return this.quizProvider.getQuizAccessInformation(quiz.id, modOptions).then((info) => { const info = await this.quizProvider.getQuizAccessInformation(quiz.id, modOptions);
return this.prefetchHandler.getPreflightData(quiz, info, onlineAttempt, askPreflight, const preflightData = await this.prefetchHandler.getPreflightData(quiz, info, onlineAttempt, askPreflight,
'core.settings.synchronization', siteId); 'core.settings.synchronization', siteId);
}).then((data) => {
preflightData = data;
// Now get the online questions data. // Now get the online questions data.
const pages = this.quizProvider.getPagesFromLayoutAndQuestions(onlineAttempt.layout, offlineQuestions); const pages = this.quizProvider.getPagesFromLayoutAndQuestions(onlineAttempt.layout, offlineQuestions);
return this.quizProvider.getAllQuestionsData(quiz, onlineAttempt, preflightData, { const onlineQuestions = await this.quizProvider.getAllQuestionsData(quiz, onlineAttempt, preflightData, {
pages, pages,
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork, readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
siteId, siteId,
}); });
}).then((onlineQuestions) => {
// Validate questions, discarding the offline answers that can't be synchronized. // Validate questions, discarding the offline answers that can't be synchronized.
return this.validateQuestions(onlineAttempt.id, onlineQuestions, offlineQuestions, siteId); const discardedData = await this.validateQuestions(onlineAttempt.id, onlineQuestions, offlineQuestions, siteId);
}).then((discardedData) => {
// Get the answers to send. // Get the answers to send.
const answers = this.quizOfflineProvider.extractAnswersFromQuestions(offlineQuestions); const answers = this.quizOfflineProvider.extractAnswersFromQuestions(offlineQuestions);
finish = offlineAttempt.finished && !discardedData; const finish = offlineAttempt.finished && !discardedData;
if (discardedData) { if (discardedData) {
if (offlineAttempt.finished) { if (offlineAttempt.finished) {
@ -396,29 +399,18 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
} }
} }
return this.quizProvider.processAttempt(quiz, onlineAttempt, answers, preflightData, finish, false, false, // Send the answers.
siteId); await this.quizProvider.processAttempt(quiz, onlineAttempt, answers, preflightData, finish, false, false, siteId);
}).then(() => {
// Answers sent, now set the current page if the attempt isn't finished.
if (!finish) { if (!finish) {
// Answers sent, now set the current page.
// Don't pass the quiz instance because we don't want to trigger a Firebase event in this case. // Don't pass the quiz instance because we don't want to trigger a Firebase event in this case.
return this.quizProvider.logViewAttempt(onlineAttempt.id, offlineAttempt.currentpage, preflightData, await CoreUtils.instance.ignoreErrors(this.quizProvider.logViewAttempt(onlineAttempt.id, offlineAttempt.currentpage,
false, undefined, siteId).catch(() => { preflightData, false, undefined, siteId));
// Ignore errors.
});
} }
}).then(() => {
// Data sent. Finish the sync. // Data sent. Finish the sync.
return this.finishSync(siteId, quiz, courseId, warnings, lastAttemptId, offlineAttempt, onlineAttempt, return this.finishSync(siteId, quiz, courseId, warnings, lastAttemptId, offlineAttempt, onlineAttempt, true, true);
true, true);
});
});
});
});
return this.addOngoingSync(quiz.id, syncPromise, siteId);
} }
/** /**