打字稿中的承诺问题
Promise issues in typescript
我一直在用打字稿试验网络音频 API。我正在创建一个 AudioDownloader
class 来下载单个或多个音频文件的音频数据和 return 单个或一组承诺。在下载多个音频文件的情况下,我不希望 Promise.all
因为一次失败而失败,所以我使用了一种名为 reflect
的方法(我从网上借来的)。
出于某种原因,由于 return 类型不匹配,download
方法中的打字稿编译失败。在过去的两天里,我一直在努力解决这个问题,但没有运气。我真的不明白我在这里犯了什么错误。有人可以帮忙吗?
class PromiseResult<T> {
value: T;
error?: any;
status: PromiseStatus;
}
enum PromiseStatus {
Resolved,
Rejected
}
function reflect<T>(promise: Promise<T>): Promise<PromiseResult<T>> {
return promise.then(v => {
return { status: PromiseStatus.Resolved, value: v };
}, e => {
return { status: PromiseStatus.Rejected, error: e }
});
}
type AudioDownloadResult = PromiseResult<AudioBuffer>;
class AudioDownloader {
private readonly context: AudioContext;
constructor(context: AudioContext) {
this.context = context;
}
download(urls: string | Array<string>): Promise<AudioDownloadResult | Array<AudioDownloadResult>> {
if (typeof urls === 'string') {
return reflect(this.downloadOne(urls as string));
}
return Promise.all((<Array<string>>urls).map(this.downloadOne).map(reflect));
}
private downloadOne(url: string): Promise<AudioDownloadResult> {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.addEventListener('load', () => {
this.context.decodeAudioData(req.response).then(buffer => {
resolve(buffer);
}, reject);
}, false);
req.addEventListener('error', reject, false);
req.send();
});
}
}
我会稍微重构函数并使其按预期工作:
class PromiseResult<T> {
value: T;
error?: any;
status: PromiseStatus;
}
enum PromiseStatus {
Resolved,
Rejected
}
type AudioDownloadResult = PromiseResult<AudioBuffer>;
class AudioDownloader {
private readonly context: AudioContext;
constructor(context: AudioContext) {
this.context = context;
}
async download(urls: string | Array<string>): Promise<AudioDownloadResult | Array<AudioDownloadResult>>
{
try
{
if (typeof urls === 'string')
{
return await this.downloadOne(urls as string);
}
let arr: AudioDownloadResult[] = [];
for (let url of urls)
{
arr.push(await this.downloadOne(url));
}
return arr;
}
catch (err)
{
return { status: PromiseStatus.Rejected, error: err } as AudioDownloadResult;
}
}
private downloadOne(url: string): Promise<AudioDownloadResult> {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.addEventListener('load', () => {
this.context.decodeAudioData(req.response).then(buffer => {
resolve(buffer);
}, reject);
}, false);
req.addEventListener('error', reject, false);
req.send();
});
}
}
我还没有测试过 - 但这应该可以。
我一直在用打字稿试验网络音频 API。我正在创建一个 AudioDownloader
class 来下载单个或多个音频文件的音频数据和 return 单个或一组承诺。在下载多个音频文件的情况下,我不希望 Promise.all
因为一次失败而失败,所以我使用了一种名为 reflect
的方法(我从网上借来的)。
出于某种原因,由于 return 类型不匹配,download
方法中的打字稿编译失败。在过去的两天里,我一直在努力解决这个问题,但没有运气。我真的不明白我在这里犯了什么错误。有人可以帮忙吗?
class PromiseResult<T> {
value: T;
error?: any;
status: PromiseStatus;
}
enum PromiseStatus {
Resolved,
Rejected
}
function reflect<T>(promise: Promise<T>): Promise<PromiseResult<T>> {
return promise.then(v => {
return { status: PromiseStatus.Resolved, value: v };
}, e => {
return { status: PromiseStatus.Rejected, error: e }
});
}
type AudioDownloadResult = PromiseResult<AudioBuffer>;
class AudioDownloader {
private readonly context: AudioContext;
constructor(context: AudioContext) {
this.context = context;
}
download(urls: string | Array<string>): Promise<AudioDownloadResult | Array<AudioDownloadResult>> {
if (typeof urls === 'string') {
return reflect(this.downloadOne(urls as string));
}
return Promise.all((<Array<string>>urls).map(this.downloadOne).map(reflect));
}
private downloadOne(url: string): Promise<AudioDownloadResult> {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.addEventListener('load', () => {
this.context.decodeAudioData(req.response).then(buffer => {
resolve(buffer);
}, reject);
}, false);
req.addEventListener('error', reject, false);
req.send();
});
}
}
我会稍微重构函数并使其按预期工作:
class PromiseResult<T> {
value: T;
error?: any;
status: PromiseStatus;
}
enum PromiseStatus {
Resolved,
Rejected
}
type AudioDownloadResult = PromiseResult<AudioBuffer>;
class AudioDownloader {
private readonly context: AudioContext;
constructor(context: AudioContext) {
this.context = context;
}
async download(urls: string | Array<string>): Promise<AudioDownloadResult | Array<AudioDownloadResult>>
{
try
{
if (typeof urls === 'string')
{
return await this.downloadOne(urls as string);
}
let arr: AudioDownloadResult[] = [];
for (let url of urls)
{
arr.push(await this.downloadOne(url));
}
return arr;
}
catch (err)
{
return { status: PromiseStatus.Rejected, error: err } as AudioDownloadResult;
}
}
private downloadOne(url: string): Promise<AudioDownloadResult> {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.addEventListener('load', () => {
this.context.decodeAudioData(req.response).then(buffer => {
resolve(buffer);
}, reject);
}, false);
req.addEventListener('error', reject, false);
req.send();
});
}
}
我还没有测试过 - 但这应该可以。