async/await devuelve implícitamente la promesa?

9 minutos de lectura

asyncawait devuelve implicitamente la promesa
alexander molinos

Leí que las funciones asíncronas marcadas por el async palabra clave devuelve implícitamente una promesa:

async function getVal(){
 return await doSomethingAync();
}

var ret = getVal();
console.log(ret);

pero eso no es coherente… suponiendo doSomethingAsync() devuelve una promesa, y la palabra clave await devolverá el valor de la promesa, no la promesa en sí, luego mi función getVal deberían devolver ese valor, no una promesa implícita.

Entonces, ¿cuál es exactamente el caso? ¿Las funciones marcadas por la palabra clave asíncrona implícitamente devuelven promesas o controlamos lo que devuelven?

¿Quizás si no devolvemos algo explícitamente, entonces implícitamente devuelven una promesa…?

Para ser más claro, hay una diferencia entre lo anterior y

function doSomethingAync(charlie) {
    return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(charlie || 'yikes');
        }, 100);
    })
}

async function getVal(){
   var val = await doSomethingAync();  // val is not a promise
   console.log(val); // logs 'yikes' or whatever
   return val;  // but this returns a promise
}

var ret = getVal();
console.log(ret);  //logs a promise

En mi sinopsis, el comportamiento es de hecho inconsistente con las declaraciones de devolución tradicionales. Parece que cuando devuelve explícitamente un valor no prometido de un async función, obligará a envolverlo en una promesa. No tengo un gran problema con eso, pero desafía a JS normal.

  • Que hace console.log ¿show?

    – Barmar

    9 de febrero de 2016 a las 21:24

  • es el valor pasado por la función de resolución de la promesa, no la promesa en sí

    – Alejandro Mills

    09/02/2016 a las 21:25


  • Quizás esperar desenvuelve el resultado de la promesa.

    – Hamlet Hakobian

    09/02/2016 a las 21:30


  • Las promesas de JavaScript intentan imitar el comportamiento de espera asíncrona de c#. Sin embargo, históricamente había mucha estructura para respaldar eso con C#, y ninguna en JavaScript. Entonces, si bien en muchos casos de uso puede parecer muy similar, es un nombre algo inapropiado.

    – Travis J.

    9 de febrero de 2016 a las 21:58

  • sí, eso es correcto, solo un poco confuso, ya que está implícito … es decir, incluso si no hay una declaración de devolución, todavía devuelve una promesa … ¿visto?

    – Alejandro Mills

    04/08/2018 a las 23:45

asyncawait devuelve implicitamente la promesa
nathan pared

El valor de retorno siempre será una promesa. Si no devuelve explícitamente una promesa, el valor que devuelva se incluirá automáticamente en una promesa.

async function increment(num) {
  return num + 1;
}

// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));

¡Lo mismo aunque no haya retorno! (Promise { undefined } es regresado)

async function increment(num) {}

Lo mismo incluso si hay un await.

function defer(callback) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(callback());
    }, 1000);
  });
}

async function incrementTwice(num) {
  const numPlus1 = await defer(() => num + 1);
  return numPlus1 + 1;
}

// Logs: 5
incrementTwice(3).then(num => console.log(num));

Las promesas se desenvuelven automáticamente, por lo que si devuelve una promesa por un valor dentro de un async función, recibirá una promesa por el valor (no una promesa por una promesa por el valor).

function defer(callback) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(callback());
    }, 1000);
  });
}

async function increment(num) {
  // It doesn't matter whether you put an `await` here.
  return defer(() => num + 1);
}

// Logs: 4
increment(3).then(num => console.log(num));

En mi sinopsis, el comportamiento es de hecho inconsistente con las declaraciones de devolución tradicionales. Parece que cuando devuelve explícitamente un valor no prometido de una función asíncrona, lo forzará a envolverlo en una promesa. No tengo un gran problema con eso, pero desafía a JS normal.

ES6 tiene funciones que no devuelven exactamente el mismo valor que el return. Estas funciones se llaman generadores.

function* foo() {
  return 'test';
}

// Logs an object.
console.log(foo());

// Logs 'test'.
console.log(foo().next().value);

  • “el valor que devuelve se envolverá automáticamente en una promesa” mediante el método estático Promise.resolve, es decir, si la declaración de devolución de una función asíncrona es – devuelve x; implícitamente se convierte en – return Promise.resolve(x);

    – adnan2nd

    12 de noviembre de 2017 a las 18:01

  • ¿Se considera una mala práctica simplemente devolver la promesa creada automáticamente en lugar de crearla explícitamente usted mismo? De alguna manera me gusta el enfoque limpio en muchos casos.

    – marlar

    15 mayo 2020 a las 18:17

  • No, no creo que sea una mala práctica confiar en la promesa creada automáticamente. Creo que una consecuencia prevista de la función asíncrona es permitirle conectarse a otras funciones de devolución de promesas sin tener que tener “Promesa” en su código. por ejemplo, función async myFunc() { const val1 = esperar a otherAsyncFunc1(); const val2 = esperar otraAsyncFunc1(); volver val1 + val 2; } function async main() { const resultado = esperar myFunc(): console.log(“El resultado es ” + resultado”); }

    – RonJRH

    20 de julio de 2021 a las 16:55


Eché un vistazo a las especificaciones y encontré la siguiente información. La versión corta es que un async function desazúcares a un generador que produce Promises. Entonces, sí, las funciones asíncronas devuelven promesas.

De acuerdo con la especificaciones tc39lo siguiente es cierto:

async function <name>?<argumentlist><body>

Desazúcares a:

function <name>?<argumentlist>{ return spawn(function*() <body>, this); }

Donde spawn “es una llamada al siguiente algoritmo”:

function spawn(genF, self) {
    return new Promise(function(resolve, reject) {
        var gen = genF.call(self);
        function step(nextF) {
            var next;
            try {
                next = nextF();
            } catch(e) {
                // finished with failure, reject the promise
                reject(e);
                return;
            }
            if(next.done) {
                // finished with success, resolve the promise
                resolve(next.value);
                return;
            }
            // not finished, chain off the yielded promise and `step` again
            Promise.resolve(next.value).then(function(v) {
                step(function() { return gen.next(v); });
            }, function(e) {
                step(function() { return gen.throw(e); });
            });
        }
        step(function() { return gen.next(undefined); });
    });
}

  • “La versión corta es que una función asíncrona se convierte en un generador que genera Promesas”. creo que puedes estar confundiendo async function con async function*. El primero simplemente devuelve una promesa. Este último devuelve un generador que produce promesas.

    – cdhowie

    9 de enero de 2020 a las 0:45

  • Esta respuesta es en gran medida una referencia a la especificación y, después de la revisión, no creo que haya confusión. Es cierto, las funciones asincrónicas devuelven promesas, pero para hacer esto, desazucaran a los generadores que generan promesas.

    – Jon Surrell

    9 de enero de 2020 a las 9:26

tu pregunta es: Si creo un async función debe devolver una promesa o no? Responder: solo haz lo que quieras y Javascript lo arreglará por ti.

Suponer doSomethingAsync es una función que devuelve una promesa. Luego

async function getVal(){
    return await doSomethingAsync();
}

es exactamente igual que

async function getVal(){
    return doSomethingAsync();
}

Probablemente estés pensando “WTF, ¿cómo pueden ser iguales?” y tienes razón. El async voluntad por arte de magia envolver un valor con una promesa si necesario.

Aún más extraño, el doSomethingAsync se puede escribir a a veces devolver una promesa y a veces NO devolver una promesa. Aún así, ambas funciones son exactamente iguales, porque el await es también magia. Desenvolverá una Promesa si necesario pero no tendrá efecto sobre las cosas que no son Promesas.

Simplemente agregue esperar antes de su función cuando la llame:

var ret = await  getVal();
console.log(ret);

async no devuelve la promesa, la palabra clave await espera la resolución de la promesa. async es una función de generador mejorada y await funciona un poco como yield

Creo que la sintaxis (no estoy 100% seguro) es

async function* getVal() {...}

Las funciones del generador ES2016 funcionan un poco así. He creado un controlador de base de datos basado en lo tedioso que programa de esta manera

db.exec(function*(connection) {
  if (params.passwd1 === '') {
    let sql="UPDATE People SET UserName = @username WHERE ClinicianID = @clinicianid";
    let request = connection.request(sql);
    request.addParameter('username',db.TYPES.VarChar,params.username);
    request.addParameter('clinicianid',db.TYPES.Int,uid);
    yield connection.execSql();
  } else {
    if (!/^\S{4,}$/.test(params.passwd1)) {
      response.end(JSON.stringify(
        {status: false, passwd1: false,passwd2: true}
      ));
      return;
    }
    let request = connection.request('SetPassword');
    request.addParameter('userID',db.TYPES.Int,uid);
    request.addParameter('username',db.TYPES.NVarChar,params.username);
    request.addParameter('password',db.TYPES.VarChar,params.passwd1);
    yield connection.callProcedure();
  }
  response.end(JSON.stringify({status: true}));

}).catch(err => {
  logger('database',err.message);
  response.end(JSON.stringify({status: false,passwd1: false,passwd2: false}));
});

Observe cómo lo programo como sincrónico normal, particularmente en

yield connection.execSql y en yield connection.callProcedure

La función db.exec es un generador basado en Promise bastante típico

exec(generator) {
  var self = this;
  var it;
  return new Promise((accept,reject) => {
    var myConnection;
    var onResult = lastPromiseResult => {
      var obj = it.next(lastPromiseResult);
      if (!obj.done) {
        obj.value.then(onResult,reject);
      } else {
       if (myConnection) {
          myConnection.release();
        }
        accept(obj.value);
      }
    };
    self._connection().then(connection => {
      myConnection = connection;
      it = generator(connection); //This passes it into the generator
      onResult();  //starts the generator
    }).catch(error => {
      reject(error);
    });
  });
}

  • async es una función de generador mejorada“- no, realmente no lo es.

    – Bergi

    10 de febrero de 2016 a las 11:52


  • Como se indicó anteriormente, las ‘funciones asíncronas’ de hecho devuelven una Promesa. Al menos conceptualmente, el punto principal de la declaración ‘async’ es envolver los valores de retorno de esa función en una promesa. Incluso puede ‘esperar’ en una función simple y antigua que devuelve una Promesa, y todo funciona, porque ‘función asíncrona’ === ‘función que devuelve Promesa’.

    – espectro

    8 de mayo de 2018 a las 7:43

  • @bergi, en realidad, es una función de generador mejorada. una función generadora que siempre devuelve una promesa… o algo así.

    – Alejandro Mills

    18 de agosto de 2018 a las 8:31

  • async es una función de generador mejorada“- no, realmente no lo es.

    – Bergi

    10 de febrero de 2016 a las 11:52


  • Como se indicó anteriormente, las ‘funciones asíncronas’ de hecho devuelven una Promesa. Al menos conceptualmente, el punto principal de la declaración ‘async’ es envolver los valores de retorno de esa función en una promesa. Incluso puede ‘esperar’ en una función simple y antigua que devuelve una Promesa, y todo funciona, porque ‘función asíncrona’ === ‘función que devuelve Promesa’.

    – espectro

    8 de mayo de 2018 a las 7:43

  • @bergi, en realidad, es una función de generador mejorada. una función generadora que siempre devuelve una promesa… o algo así.

    – Alejandro Mills

    18 de agosto de 2018 a las 8:31

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad