Cuando escribo una función asíncrona, generalmente devuelve una promesa:
export const myPromiseFunction = async (params) => { // some logic return Promise.resolve('resolved-value'); });Pero me preguntaba si sería un error si esta función no devolviera una promesa, por ejemplo:
export const myPromiseFunction = async (params) => { // some logic params.map(async (param) => { await printParam(param); async function printParam(par) { // do some other stuff Printer.print(par); }); }); }); export class Printer { public static async print(par) {console.log(par);} // I know it could not be async, but for the sake lets suppose it does }¿Es esto un error/mala práctica? ¿O podemos encontrar un escenario en el que esto sea válido y deseable?
Todas las funciones async devuelven promesas automáticamente. Si declara una función como async , devolverá una Promesa, incluso si su único valor de return es un valor simple como una cadena o un número. Si no regresa explícitamente, su función async aún devolverá una Promesa con un valor de undefined .
De hecho, es más común que el cuerpo de una función async devuelva un valor simple en lugar de una promesa; la suposición es que su función es async porque await las promesas que consume dentro de ella. Como consecuencia, incluso si devuelve el valor 5, el valor devuelto es una Promesa (que se resuelve en 5) que representa el retraso potencial que proviene de cualquier expresión de await en la función.
No tiene que devolver un objeto Promise explícitamente en su función async , y es redundante hacerlo si solo está envolviendo un valor simple como 'resolved-value' . Por el contrario, puede hacer que una función normal se comporte como una función async si siempre devuelve una Promesa (potencialmente con Promise.resolve) y nunca arroja un error sincrónicamente dentro de ella.
async function myFunction() { makeSomeCall(); // Happens immediately. await someOtherPromise(); // myFunction returns a Promise // before someOtherPromise resolves; if it // does without error, the returned Promise return 5; // resolves to 5. } /** Behaves the same as the above function. */ function myFunctionButNotAsync() { try { makeSomeCall(); // If you didn't have someOtherPromise() to wait for here, then // this is where Promise.resolve(5) would be useful to return. return someOtherPromise().then(() => 5); } catch (e) { return Promise.reject(e); } } Dicho todo esto, es posible que tenga la oportunidad de devolver explícitamente un objeto Promise (como uno producido por Promise.all o una función de devolución de Promise separada), que luego observa reglas similares a las que observa Promise.resolve() : Si el objeto que el retorno de una función async es una Promesa, o tiene una función then , entonces la Promesa automática que devuelve la función async esperará la Promesa específica o el objeto similar a una Promesa que devuelva con return .
async function myFunction() { makeSomeCall(); // Happens immediately. await anythingElse(); // You can still await other things. return someOtherPromise(); // The promise myFunction returns will take // the same outcome as the Promise that // someOtherPromise() returns. } En un sentido relacionado, esta es la razón por la que return await se considera redundante , aunque, como se describe, hace una diferencia para los seguimientos de la pila que ve si se rechaza la promesa envuelta.
Respuesta corta: no, una función async no tiene que devolver una Promesa. En realidad, generalmente no devolvería un objeto Promise (a menos que esté encadenando eventos asíncronos).
Lo que hacen async y await es esperar una respuesta de algo que devuelve una Promesa.
Su primer ejemplo de código en realidad devuelve una Promesa resuelta . Pero, ¿qué sucede si la Promesa no se resuelve correctamente?
Es mejor llamar a una función que devuelve una Promesa de otra función async :
function getRequestResult() { return new Promise(resolve => { setTimeout(() => { resolve('request sent'); }, 2000); }); } async function sendMyRequest() { console.log('Sending request'); const result = await getRequestResult(); console.log(result); // expected output: "resolved" } Puede enviar rechazos/errores dentro de getRequestResult() de esa manera, y también administrar cómo estos errores serán manejados por la llamada en sendMyRequest() (ver https://developer.mozilla.org/en-US/docs/Web/JavaScript /Referencia/Operadores/esperar ).