2017-01-19 6 views
1

私はtypescriptでWeb Audio APIを試しています。私はAudioDownloaderクラスを作成して、1つまたは複数のオーディオファイルのオーディオデータをダウンロードし、1つまたは複数の約束を返します。複数のオーディオファイルをダウンロードする場合、私はPromise.allが単一の失敗のために失敗するのを避けたいので、reflect(ネットから借りたもの)というメソッドを使用しました。タイプコピーの約束

何らかの理由により、戻りコードの型が一致しないため、downloadメソッドで型コピーのコンパイルが失敗します。私は運がない最後の2日間これを整理しようとしてきました。私はここで何をしているのか分かりません。誰かが助けてくれますか?

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

戻り値の型が 'downloadOne'メソッドの' Promise 'で 'Promise 'ではありません – VJAI

答えて

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(); 
     }); 
    } 
} 

私はそれをテストしていません - しかし、これは仕事を行う必要があります。

+0

もしオーディオがダウンロードできない場合、上記のコードで他の約束が解決されますか? – VJAI

+0

上記のコードは期待どおりに機能していません。 1つのダウンロードが失敗した場合、それはまっすぐにcatchブロックに来ます。 – VJAI

+1

ループを継続させるためにtry/catchを使って 'arr.push(await this.downloadOne(url));'をラップします。 – Amid