Похоже, здесь есть некоторая путаница относительно того, как правильно использовать Обещания на нескольких уровнях.
Обратный вызов и Обещание используются неправильно
Если функция должна принимать обратный вызов, не возвращайте Обещание. Если функция должна вернуть Обещание, используйте обратный вызов, данный Обещанием:
const transactionSession = await mongoose.startSession()
await transactionSession.withTransaction( (tSession) => {
return new Promise( (resolve, reject) => {
//using Node-style callback
doSomethingAsync( (err, testData) => {
if(err) {
reject(err);
} else {
resolve(testData); //this is the equivalent of cb(null, "Any test data")
}
});
})
Давайте рассмотрим это более подробно:
return new Promise( (resolve, reject) => {
Это создаст новое Обещание, и Обещание дает вам два обратных вызова для использования. resolve
является обратным вызовом для указания успеха. Вы передаете ему объект, который хотите вернуть. Обратите внимание, что я удалил ключевое слово async
(подробнее об этом позже).
Например:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Эта функция используется для сопоставления стиля узла cb(err, result)
с обратными вызовами Promise.
Try / catch используются неправильно.
Try / catch может использоваться только для синхронных операторов. Давайте сравним синхронный вызов, асинхронный обратный вызов в стиле узла (то есть cb(err, result)
), обещание и использование await:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Ожидайте. Await может использоваться с любой функцией, которая возвращает Promise и позволяет обрабатывать код, как если бы он был синхронным:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Дополнительная информация
Promise.resolve()
Promise.resolve()
создает новое Обещание и разрешает это Обещание с неопределенным значением. Это сокращение для:
new Promise( (resolve, reject) => resolve(undefined) );
Эквивалент обратного вызова этого будет:
cb(err, undefined);
async
async
идет с await
. Если вы используете await
в функции, эта функция должна быть объявлена как async
.
Так же, как await
разворачивает Обещание (resolve
в значение и reject
в исключение), async
оборачивает код в Обещание. Оператор return value
переводится в Promise.resolve(value)
, а выброшенное исключение throw e
переводится в Promise.reject(e)
.
Рассмотрим следующий код
async () => {
return doSomethingSync();
}
Приведенный выше код эквивалентен следующему:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Если вы вызываете любую из вышеуказанных функций без await
, вы вернется обещание. Если вы await
любой из них, вам будет возвращено значение, или будет сгенерировано исключение.