Hay una pequeña pero importante diferencia entre una función que simplemente devuelve una promesa y una función que se declaró utilizando la 
async .
Eche un vistazo al siguiente fragmento de código: 
 function fn(obj) { const someProp = obj.someProp return Promise.resolve(someProp) } async function asyncFn(obj) { const someProp = obj.someProp return Promise.resolve(someProp) } asyncFn().catch(err => console.error('Catched'))  
Como puede ver, ambas funciones tienen el mismo cuerpo en el que estamos tratando de acceder a la propiedad de un argumento que no está definido en ambos casos. La única diferencia entre las dos funciones es que 
asyncFn declara utilizando la 
async .
Esto significa que JavaScript garantiza que la función 
asnycFn devuelva una promesa (ya sea exitosa o fallida), incluso si se produce un error en ella, en nuestro caso el bloque 
.catch() detectará.
Sin embargo, en el caso de la función 
fn , el motor aún no sabe que la función devolverá una promesa y, por lo tanto, el código no alcanzará el bloque 
.catch() , el error no se detectará y caerá en la consola.
Más ejemplo de vida
Sé lo que estás pensando ahora:
"¿Cuándo diablos cometeré tal error?"
Adivinado?
Bueno, creemos una aplicación simple que haga exactamente eso.
Supongamos que tenemos una aplicación creada con Express y MongoDB que usa el controlador MongoDB Node.JS. Si no confía en mí, he colocado todo el código fuente en 
este repositorio de Github , para que pueda clonarlo y ejecutarlo localmente, pero también duplicaré todo el código aquí.
Aquí está nuestro archivo 
app.js :
 
¡Mira de cerca el bloque 
.catch() ! Aquí es donde ocurrirá la magia (no).
El archivo 
db.js utiliza para conectarse a la base de datos mongo:
 'use strict' const MongoClient = require('mongodb').MongoClient const url = 'mongodb://localhost:27017' const dbName = 'async-promise-test' const client = new MongoClient(url) let db module.exports = { connect() { return new Promise((resolve, reject) => { client.connect(err => { if (err) return reject(err) console.log('Connected successfully to server') db = client.db(dbName) resolve(db) }) }) }, getDb() { return db } } 
Y finalmente, tenemos un archivo 
user-model.js en el que actualmente solo se define una función 
getUserById :
 
Si 
app.js a mirar el archivo 
app.js , verá que cuando vamos a 
localhost:3000/users/<id> llamamos a la función 
getUserById definida en el 
user-model.js , pasando el parámetro 
id como solicitud.
Digamos que usted va a la siguiente dirección: 
localhost:3000/users/1 . ¿Qué crees que pasará después?
Bueno, si respondiste: "Veré un gran error de MongoClient", tenías razón. Para ser más precisos, verá el siguiente error: 
Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters .
¿Y crees que se 
.catch() bloque 
.catch() en el siguiente fragmento de código?
 
No No será llamado.
¿Y qué sucede si cambia una declaración de función a esto?
 module.exports = {  
Sí, comienzas a entender qué es qué. Se 
.catch() nuestro bloque 
.catch() , y podremos procesar el error detectado y mostrárselo al usuario.
En lugar de una conclusión
Espero que esta información haya sido útil para algunos de ustedes. Tenga en cuenta que este artículo no intenta obligarlo a usar siempre funciones asincrónicas, aunque son bastante geniales. Tienen sus propios casos de uso, pero siguen siendo azúcar sintáctica por encima de las promesas.
Solo quería que supieras que a veces las promesas pueden hacer una gran diferencia, y cuando (sí, no "si") encuentras el error discutido en este artículo, sabrás la posible razón de su ocurrencia.
Nota PS perev.: al artículo original, se dejó un comentario útil del usuario Craig P Hicks, que (después de los comentarios en los comentarios) decidí citar aquí:Me gustaría llamar la atención sobre un detalle, (en mi entorno de desarrollo) los errores que ocurren en el cuerpo de Promise.resolve({<body>}) no se "detectan":
 Promise.resolve((()=>{throw "oops"; })()) .catch(e=>console("Catched ",e));  
pero los errores que ocurren en el cuerpo de la new Promise() ( aprox. traducción: en la "Promesa apropiada" original ) son "atrapados":
 (new Promise((resolve,reject)=>{ resolve((()=>{throw "oops"})()) })) .catch(e=>console.log("Catched ",e));  
¿Qué tal esta declaración:
 async function fn() { <body> } 
semánticamente, esta opción es equivalente a esto:
 function fn() { return new Promise((resolve,reject)=>{ resolve({ <body> }) }) } 
En consecuencia, el siguiente fragmento de código detectará errores si el <cuerpo> tiene una new Promise() ( aprox. Traducción: en la "Promesa apropiada" original ):
 function fn() { return Promise.resolve({<body}); } 
Por lo tanto, para que el ejemplo del principio del artículo "atrape" los errores en ambos casos, es necesario devolver no Promise.resolve() , sino new Promise() en las funciones: function fn(obj) { return new Promise((resolve, reject) => { const someProp = obj.someProp; resolve(someProp); }); } async function asyncFn(obj) { return new Promise((resolve, reject) => { const someProp = obj.someProp; resolve(someProp); }); } asyncFn().catch(err => console.error("Catched"));