2017-01-19 4 views
1

Ich habe Web Audio API mit Typoskript experimentiert. Ich bin dabei, eine Klasse AudioDownloader zu erstellen, die die Audiodaten für eine einzelne oder mehrere Audiodateien herunterlädt und eine oder mehrere Versprechen zurückgibt. Im Fall des Herunterladens mehrerer Audiodateien möchte ich nicht, dass die Promise.all wegen eines einzelnen Fehlers fehlschlägt, also verwendete ich eine Methode namens reflect (die ich aus dem Netz ausgeliehen habe).Versprechen Probleme in Typoskript

Aus irgendeinem Grund fehlschlägt die Typoskript-Kompilierung in der download-Methode aufgrund von Fehlübereinstimmung im Rückgabetyp. Ich habe versucht, dies für die letzten zwei Tage ohne Glück zu sortieren. Ich verstehe wirklich nicht, was ich hier mache. Kann mir bitte jemand helfen?

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

Ich fand das Problem im Code der Rückgabetyp von 'downloadOne' Methode sollte' Promise 'nicht' Promise ' – VJAI

Antwort

1

würde ich Funktionen ein wenig Refactoring und bekommen es, indem Sie so wie erwartet funktionieren:

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

ich es getestet haben, nicht - aber dies sollte die Arbeit machen.

+0

Wenn einer der Audio schlägt fehl, funktioniert die anderen Versprechen in dem oben genannten Code? – VJAI

+0

Der obige Code funktioniert nicht wie erwartet. Wenn ein Download fehlschlägt, kommt es direkt zum catch-Block. – VJAI

+1

Es ist sehr einfach, das Verhalten so zu ändern, dass es so funktioniert, wie Sie es brauchen: wrap 'arr.push (wartet auf diese.downloadOne (url));' mit try/catch, damit die Schleife fortgesetzt wird – Amid

Verwandte Themen