Estoy tratando de entender la relación entre async / await y Promise s en TypeScript y creo que me confundí demasiado.
En particular, estoy tratando de entender cómo la versión async / await de una función de ejemplo, downloadFileAA , definida a continuación, se asigna a una implementación que usa Promise s en su lugar. ¿Qué está pasando detrás de escena con Promise s? Obviamente, ninguna de mis versiones de Promise es satisfactoria ni captura por completo lo que sucede en la versión async /en await ( downloadFilePromise nunca informa sobre el éxito o el fracaso, y downloadFilePromise2 requiere una extraña redundancia: result.then() en el argumento para resolve pasar la verificación de tipo) , pero no estoy seguro de por qué.
¿Cómo sería una versión basada en Promise de downloadFileAA ? ¿Hay alguna razón para preferirlo (o no) a la versión async / await ?
import * as FileSystem from 'expo-file-system' const callback = ( downloadProgress ) => { const progress = downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite console.log( `${Number( progress ) .toLocaleString( undefined, { style: 'percent', minimumFractionDigits: 0 } ) .padStart( 5, ' ' )} of ${downloadProgress.totalBytesExpectedToWrite} bytes` ) } const downloadResumable = FileSystem.createDownloadResumable( 'http://...', FileSystem.documentDirectory + 'somebigfile', {}, callback ) const downloadFileAA = async () => { try { console.log( 'Starting download (with async/await)... ' ) const result = await downloadResumable.downloadAsync() console.log( result ? `Finished downloading to ${result.uri}` : 'Undefined result?' ) } catch ( e ) { console.error( `Failed download: ${e.message}` ) } } const downloadFilePromise = () => { console.log( 'Starting download (with Promise)... ' ) new Promise<FileSystem.FileSystemDownloadResult>( ( resolve, reject ) => downloadResumable.downloadAsync() ) .then( ( result ) => console.log( `Finished downloading to ${result.uri}` ) ) .catch( ( reason ) => console.error( `Failed download: ${reason}` ) ) } const downloadFilePromise2 = () => { console.log( 'Starting download (with Promise Two)... ' ) new Promise<FileSystem.FileSystemDownloadResult>( ( resolve, reject ) => { const result = downloadResumable.downloadAsync() result ? resolve( result.then() ) : reject( result ) } ) .then( ( result ) => console.log( `Finished downloading to ${result.uri}` ) ) .catch( ( reason ) => console.error( `Failed download: ${reason}` ) ) }Asumiendo que downloadAsync devuelve una Promesa y que console.log no arroja, esto
const downloadFileAA = async () => { try { console.log( 'Starting download (with async/await)... ' ) const result = await downloadResumable.downloadAsync() console.log( result ? `Finished downloading to ${result.uri}` : 'Undefined result?' ) } catch ( e ) { console.error( `Failed download: ${e.message}` ) } }es equivalente a
const downloadFileAA = () => { console.log('Starting download (with async/await)... ') return downloadResumable.downloadAsync() .then((result) => { console.log(result ? `Finished downloading to ${result.uri}` : 'Undefined result?') }) .catch((e) => { console.error(`Failed download: ${e.message}`); }); }; Lo que hace await es reemplazar .then . No reemplaza las Promesas: tanto await como .then requieren una Promesa (al menos para usarse con sensatez).
Su función downloadFilePromise está rota porque construye una Promesa que, por definición, nunca se resuelve; debe llamar al argumento de resolve o reject para que la Promesa construida se resuelva. Pero dado que parece que downloadAsync ya devuelve una Promesa, construir otra Promesa que la rodee no tiene ningún sentido ; solo use la Promesa que tiene en lugar de hacer una nueva.
¿Hay alguna razón para preferirlo (o no) a la versión async/await?
Es puramente una elección estilística. IMO await brilla mejor cuando hay múltiples valores que deben esperarse (en serie), pero de lo contrario funcionan bien (siempre que se implementen correctamente, por supuesto).