@euirim/microsoft-cognitiveservices-speech-sdk
Version:
Microsoft Cognitive Services Speech SDK for JavaScript
340 lines (338 loc) • 12.3 kB
JavaScript
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ArgumentNullError } from "./Error";
export var PromiseState;
(function (PromiseState) {
PromiseState[PromiseState["None"] = 0] = "None";
PromiseState[PromiseState["Resolved"] = 1] = "Resolved";
PromiseState[PromiseState["Rejected"] = 2] = "Rejected";
})(PromiseState || (PromiseState = {}));
export class PromiseResult {
constructor(promiseResultEventSource) {
this.throwIfError = () => {
if (this.isError) {
throw this.error;
}
};
promiseResultEventSource.on((result) => {
if (!this.privIsCompleted) {
this.privIsCompleted = true;
this.privIsError = false;
this.privResult = result;
}
}, (error) => {
if (!this.privIsCompleted) {
this.privIsCompleted = true;
this.privIsError = true;
this.privError = error;
}
});
}
get isCompleted() {
return this.privIsCompleted;
}
get isError() {
return this.privIsError;
}
get error() {
return this.privError;
}
get result() {
return this.privResult;
}
}
// tslint:disable-next-line:max-classes-per-file
export class PromiseResultEventSource {
constructor() {
this.setResult = (result) => {
this.privOnSetResult(result);
};
this.setError = (error) => {
this.privOnSetError(error);
};
this.on = (onSetResult, onSetError) => {
this.privOnSetResult = onSetResult;
this.privOnSetError = onSetError;
};
}
}
// tslint:disable-next-line:max-classes-per-file
export class PromiseHelper {
}
PromiseHelper.whenAll = (promises) => {
if (!promises || promises.length === 0) {
throw new ArgumentNullError("promises");
}
const deferred = new Deferred();
const errors = [];
let completedPromises = 0;
const checkForCompletion = () => {
completedPromises++;
if (completedPromises === promises.length) {
if (errors.length === 0) {
deferred.resolve(true);
}
else {
deferred.reject(errors.join(", "));
}
}
};
for (const promise of promises) {
promise.on((r) => {
checkForCompletion();
}, (e) => {
errors.push(e);
checkForCompletion();
});
}
return deferred.promise();
};
PromiseHelper.fromResult = (result) => {
const deferred = new Deferred();
deferred.resolve(result);
return deferred.promise();
};
PromiseHelper.fromError = (error) => {
const deferred = new Deferred();
deferred.reject(error);
return deferred.promise();
};
// TODO: replace with ES6 promises
// tslint:disable-next-line:max-classes-per-file
export class Promise {
constructor(sink) {
this.result = () => {
return this.privSink.result;
};
this.continueWith = (continuationCallback) => {
if (!continuationCallback) {
throw new ArgumentNullError("continuationCallback");
}
const continuationDeferral = new Deferred();
this.privSink.on((r) => {
try {
const continuationResult = continuationCallback(this.privSink.result);
continuationDeferral.resolve(continuationResult);
}
catch (e) {
continuationDeferral.reject(e);
}
}, (error) => {
try {
const continuationResult = continuationCallback(this.privSink.result);
continuationDeferral.resolve(continuationResult);
}
catch (e) {
continuationDeferral.reject(`'Error handler for error ${error} threw error ${e}'`);
}
});
return continuationDeferral.promise();
};
this.onSuccessContinueWith = (continuationCallback) => {
if (!continuationCallback) {
throw new ArgumentNullError("continuationCallback");
}
const continuationDeferral = new Deferred();
this.privSink.on((r) => {
try {
const continuationResult = continuationCallback(r);
continuationDeferral.resolve(continuationResult);
}
catch (e) {
continuationDeferral.reject(e);
}
}, (error) => {
continuationDeferral.reject(error);
});
return continuationDeferral.promise();
};
this.continueWithPromise = (continuationCallback) => {
if (!continuationCallback) {
throw new ArgumentNullError("continuationCallback");
}
const continuationDeferral = new Deferred();
this.privSink.on((r) => {
try {
const continuationPromise = continuationCallback(this.privSink.result);
if (!continuationPromise) {
throw new Error("'Continuation callback did not return promise'");
}
continuationPromise.on((continuationResult) => {
continuationDeferral.resolve(continuationResult);
}, (e) => {
continuationDeferral.reject(e);
});
}
catch (e) {
continuationDeferral.reject(e);
}
}, (error) => {
try {
const continuationPromise = continuationCallback(this.privSink.result);
if (!continuationPromise) {
throw new Error("Continuation callback did not return promise");
}
continuationPromise.on((continuationResult) => {
continuationDeferral.resolve(continuationResult);
}, (e) => {
continuationDeferral.reject(e);
});
}
catch (e) {
continuationDeferral.reject(`'Error handler for error ${error} threw error ${e}'`);
}
});
return continuationDeferral.promise();
};
this.onSuccessContinueWithPromise = (continuationCallback) => {
if (!continuationCallback) {
throw new ArgumentNullError("continuationCallback");
}
const continuationDeferral = new Deferred();
this.privSink.on((r) => {
try {
const continuationPromise = continuationCallback(r);
if (!continuationPromise) {
throw new Error("Continuation callback did not return promise");
}
continuationPromise.on((continuationResult) => {
continuationDeferral.resolve(continuationResult);
}, (e) => {
continuationDeferral.reject(e);
});
}
catch (e) {
continuationDeferral.reject(e);
}
}, (error) => {
continuationDeferral.reject(error);
});
return continuationDeferral.promise();
};
this.on = (successCallback, errorCallback) => {
if (!successCallback) {
throw new ArgumentNullError("successCallback");
}
if (!errorCallback) {
throw new ArgumentNullError("errorCallback");
}
this.privSink.on(successCallback, errorCallback);
return this;
};
this.finally = (callback) => {
if (!callback) {
throw new ArgumentNullError("callback");
}
const callbackWrapper = (_) => {
callback();
};
return this.on(callbackWrapper, callbackWrapper);
};
this.privSink = sink;
}
}
// tslint:disable-next-line:max-classes-per-file
export class Deferred {
constructor() {
this.state = () => {
return this.privSink.state;
};
this.promise = () => {
return this.privPromise;
};
this.resolve = (result) => {
this.privSink.resolve(result);
return this;
};
this.reject = (error) => {
this.privSink.reject(error);
return this;
};
this.privSink = new Sink();
this.privPromise = new Promise(this.privSink);
}
}
// tslint:disable-next-line:max-classes-per-file
export class Sink {
constructor() {
this.privState = PromiseState.None;
this.privPromiseResult = null;
this.privPromiseResultEvents = null;
this.privSuccessHandlers = [];
this.privErrorHandlers = [];
this.resolve = (result) => {
if (this.privState !== PromiseState.None) {
throw new Error("'Cannot resolve a completed promise'");
}
this.privState = PromiseState.Resolved;
this.privPromiseResultEvents.setResult(result);
for (let i = 0; i < this.privSuccessHandlers.length; i++) {
this.executeSuccessCallback(result, this.privSuccessHandlers[i], this.privErrorHandlers[i]);
}
this.detachHandlers();
};
this.reject = (error) => {
if (this.privState !== PromiseState.None) {
throw new Error("'Cannot reject a completed promise'");
}
this.privState = PromiseState.Rejected;
this.privPromiseResultEvents.setError(error);
for (const errorHandler of this.privErrorHandlers) {
this.executeErrorCallback(error, errorHandler);
}
this.detachHandlers();
};
this.on = (successCallback, errorCallback) => {
if (successCallback == null) {
successCallback = (r) => { return; };
}
if (this.privState === PromiseState.None) {
this.privSuccessHandlers.push(successCallback);
this.privErrorHandlers.push(errorCallback);
}
else {
if (this.privState === PromiseState.Resolved) {
this.executeSuccessCallback(this.privPromiseResult.result, successCallback, errorCallback);
}
else if (this.privState === PromiseState.Rejected) {
this.executeErrorCallback(this.privPromiseResult.error, errorCallback);
}
this.detachHandlers();
}
};
this.executeSuccessCallback = (result, successCallback, errorCallback) => {
try {
successCallback(result);
}
catch (e) {
this.executeErrorCallback(`'Unhandled callback error: ${e}'`, errorCallback);
}
};
this.executeErrorCallback = (error, errorCallback) => {
if (errorCallback) {
try {
errorCallback(error);
}
catch (e) {
throw new Error(`'Unhandled callback error: ${e}. InnerError: ${error}'`);
}
}
else {
throw new Error(`'Unhandled error: ${error}'`);
}
};
this.detachHandlers = () => {
this.privErrorHandlers = [];
this.privSuccessHandlers = [];
};
this.privPromiseResultEvents = new PromiseResultEventSource();
this.privPromiseResult = new PromiseResult(this.privPromiseResultEvents);
}
get state() {
return this.privState;
}
get result() {
return this.privPromiseResult;
}
}
//# sourceMappingURL=Promise.js.map