2017-01-19 5 views
1

웹 오디오 API를 타이프 ​​스크립트로 실험 해 왔습니다. 나는 하나 또는 여러 개의 오디오 파일에 대한 오디오 데이터를 다운로드하고 약속의 단일 또는 배열을 반환하는 AudioDownloader 클래스를 만드는 중입니다. 여러 오디오 파일을 다운로드 할 경우 Promise.all이 단일 오류로 인해 실패하기를 원하지 않으므로 reflect (net에서 빌린) 메서드를 사용했습니다.타이프 스크립트의 약속 문제

어떤 이유로 든 반환 유형이 일치하지 않아 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

위 코드가 예상대로 작동하지 않습니다. 한 번의 다운로드가 실패하면 곧장 블록을 잡습니다. – VJAI

+1

루프가 계속 실행되도록하려면 try/catch를 사용하여'arr.push (this.downloadOne (url));을 기다려주십시오. – Amid

관련 문제