我一直在试用带有打字稿的Web Audio API。我正在创建一个AudioDownloader
类,用于下载单个或多个音频文件的音频数据,并返回一个或一组promises。在下载多个音频文件的情况下,我不希望Promise.all
由于单个故障而失败,所以我使用了一个名为reflect
的方法(我从网上借来的)。
由于某些原因,由于返回类型不匹配,打字稿编译在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();
});
}
}
答案 0 :(得分:1)
我会稍微重构函数并通过这样做让它按预期工作:
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();
});
}
}
我还没有测试过 - 但这应该可以胜任。