diff --git a/src/shared/util.js b/src/shared/util.js index daac2f9c3..29993afd7 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -972,23 +972,36 @@ function isSpace(ch) { * Promise Capability object. * * @typedef {Object} PromiseCapability - * @property {Promise} promise - A promise object. - * @property {function} resolve - Fulfills the promise. - * @property {function} reject - Rejects the promise. + * @property {Promise} promise - A Promise object. + * @property {boolean} settled - If the Promise has been fulfilled/rejected. + * @property {function} resolve - Fulfills the Promise. + * @property {function} reject - Rejects the Promise. */ /** * Creates a promise capability object. * @alias createPromiseCapability * - * @return {PromiseCapability} A capability object contains: - * - a Promise, resolve and reject methods. + * @return {PromiseCapability} */ function createPromiseCapability() { - var capability = {}; - capability.promise = new Promise(function (resolve, reject) { - capability.resolve = resolve; - capability.reject = reject; + const capability = Object.create(null); + let isSettled = false; + + Object.defineProperty(capability, 'settled', { + get() { + return isSettled; + }, + }); + capability.promise = new Promise(function(resolve, reject) { + capability.resolve = function(data) { + isSettled = true; + resolve(data); + }; + capability.reject = function(reason) { + isSettled = true; + reject(reason); + }; }); return capability; } diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index e66e653e8..025d1158b 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -64,14 +64,11 @@ describe('api', function() { it('creates pdf doc from URL', function(done) { var loadingTask = getDocument(basicApiGetDocumentParams); - var isProgressReportedResolved = false; var progressReportedCapability = createPromiseCapability(); - // Attach the callback that is used to report loading progress; // similarly to how viewer.js works. loadingTask.onProgress = function (progressData) { - if (!isProgressReportedResolved) { - isProgressReportedResolved = true; + if (!progressReportedCapability.settled) { progressReportedCapability.resolve(progressData); } }; @@ -183,25 +180,20 @@ describe('api', function() { function (done) { var loadingTask = getDocument(buildGetDocumentParams('pr6531_1.pdf')); - var isPasswordNeededResolved = false; var passwordNeededCapability = createPromiseCapability(); - var isPasswordIncorrectResolved = false; var passwordIncorrectCapability = createPromiseCapability(); - // Attach the callback that is used to request a password; // similarly to how viewer.js handles passwords. loadingTask.onPassword = function (updatePassword, reason) { if (reason === PasswordResponses.NEED_PASSWORD && - !isPasswordNeededResolved) { - isPasswordNeededResolved = true; + !passwordNeededCapability.settled) { passwordNeededCapability.resolve(); updatePassword('qwerty'); // Provide an incorrect password. return; } if (reason === PasswordResponses.INCORRECT_PASSWORD && - !isPasswordIncorrectResolved) { - isPasswordIncorrectResolved = true; + !passwordIncorrectCapability.settled) { passwordIncorrectCapability.resolve(); updatePassword('asdfasdf'); // Provide the correct password. diff --git a/test/unit/util_spec.js b/test/unit/util_spec.js index f61a835dd..4d67f5815 100644 --- a/test/unit/util_spec.js +++ b/test/unit/util_spec.js @@ -14,9 +14,10 @@ */ import { - bytesToString, createValidAbsoluteUrl, getInheritableProperty, isArrayBuffer, - isBool, isEmptyObj, isNum, isSameOrigin, isSpace, isString, log2, - ReadableStream, removeNullCharacters, stringToBytes, stringToPDFString, URL + bytesToString, createPromiseCapability, createValidAbsoluteUrl, + getInheritableProperty, isArrayBuffer, isBool, isEmptyObj, isNum, + isSameOrigin, isSpace, isString, log2, ReadableStream, removeNullCharacters, + stringToBytes, stringToPDFString, URL } from '../../src/shared/util'; import { Dict, Ref } from '../../src/core/primitives'; import { XRefMock } from './test_utils'; @@ -384,4 +385,35 @@ describe('util', function() { .toEqual(null); }); }); + + describe('createPromiseCapability', function() { + it('should resolve with correct data', function(done) { + const promiseCapability = createPromiseCapability(); + expect(promiseCapability.settled).toEqual(false); + + promiseCapability.resolve({ test: 'abc', }); + + promiseCapability.promise.then(function(data) { + expect(promiseCapability.settled).toEqual(true); + + expect(data).toEqual({ test: 'abc', }); + done(); + }, done.fail); + }); + + it('should reject with correct reason', function(done) { + const promiseCapability = createPromiseCapability(); + expect(promiseCapability.settled).toEqual(false); + + promiseCapability.reject(new Error('reason')); + + promiseCapability.promise.then(done.fail, function(reason) { + expect(promiseCapability.settled).toEqual(true); + + expect(reason instanceof Error).toEqual(true); + expect(reason.message).toEqual('reason'); + done(); + }); + }); + }); }); diff --git a/web/base_viewer.js b/web/base_viewer.js index d3f03214c..416602dca 100644 --- a/web/base_viewer.js +++ b/web/base_viewer.js @@ -395,8 +395,7 @@ class BaseViewer { }); }); - let isOnePageRenderedResolved = false; - let onePageRenderedCapability = createPromiseCapability(); + const onePageRenderedCapability = createPromiseCapability(); this.onePageRendered = onePageRenderedCapability.promise; let bindOnAfterAndBeforeDraw = (pageView) => { @@ -407,8 +406,7 @@ class BaseViewer { this._buffer.push(pageView); }; pageView.onAfterDraw = () => { - if (!isOnePageRenderedResolved) { - isOnePageRenderedResolved = true; + if (!onePageRenderedCapability.settled) { onePageRenderedCapability.resolve(); } };