Хотя я думал, что правильно использую ключевые слова Async и Await, похоже, что я делаю что-то не так.
Я использую PouchDB, отличную базу данных Javascript, которая синхронизируется с CouchDB. PouchDB использует обещания для многих своих функций и имеет встроенную поддержку Async и Await. Например, чтобы получить основную информацию о базе данных, вы должны использовать следующий код:
db.info().then(function (info) {
console.info(info);
})
Я это понимаю, и это работает. Но если я попытаюсь поместить это в функцию, а затем вызвать эту функцию, все пойдет наперекосяк. И я уверен, что проблема во мне, а не в PouchDB...
function getLocalDBInfo(db){
try {
db.info().then(function (info) {
return info;
});
} catch (error) {
console.info("can't get local DB info: ", error);
}
}
async function testing(db){
try {
var info=await getLocalDBInfo(db);
await console.info("DB info = ", info);
await console.info("Doc count= ", info.doc_count);
}
catch(err){
console.info("error = ",err);
}
//info contains...
//{"doc_count":0,"update_seq":0,"db_name":"kittens"}
}
testing(MY_db);
Если я зарегистрирую info
внутри функции getLocalDBInfo
, она в конечном итоге (то есть после выполнения обещания) выведет info
на консоль. Но журналы внутри функции testing
немедленно возвращаются с undefined
. Для меня имеет смысл, что они возвращаются undefined
, потому что они возвращаются немедленно, но я пытался заставить их ждать info
, используя async
и await
. Любые предложения относительно того, что я делаю неправильно?
@crashmstr Большое спасибо за ответ. Я не помечал getLocalDBInfo как асинхронный, потому что он использует обычную структуру обещаний и, согласно PouchDB, является обещанием. Может быть, я ошибался? Я думаю, что информация является результатом обещания, а не самого обещания. Если я регистрирую информацию, она в конечном итоге показывает выполненное обещание в консоли, поэтому информация в конечном итоге приводит к чему-то, но вы говорите, что возврат самого обещания, а не только результата, - это путь?
getLocalDBInfo() не возвращает обещание, поэтому вы не можете его дождаться.
с помощью async/await вы можете:
async function getLocalDBInfo(db){
try{
return await db.info()
} catch (err){
console.info("can't get local DB info: ", error);
}
}
вы также можете использовать новое обещание
Я отметил это как решение, но все ответы говорят об одном и том же: вернуть обещание, а не результат обещания. В нескольких ответах предлагалось пометить функцию getLocalDBInfo
как Async
, но, в конце концов, в этом не было необходимости, и единственное требуемое изменение — это return db.info()
. Я подозреваю, что не было необходимости помечать функцию getLocalDBInfo
как асинхронную, потому что db.info()
уже является обещанием через API PouchDB, но я рад, что меня исправили.
вы правы, в примере я разрешаю db.info внутри getLocalDBInfo и возвращаю новое обещание, если вы не делаете getLocalDBInfo асинхронным, вы просто передаете обещание db.info вокруг
Я сделал это, чтобы обработка ошибок могла происходить в функции-оболочке, поскольку блоки try-catch запускаются, когда промисы разрешаются.
Отличный материал. Это имеет смысл для меня. Спасибо за ваши ответы. Я пытаюсь лучше понять этот материал (я сделал несколько руководств, просмотрел спецификацию, провел дополнительные исследования и поэкспериментировал с ней), но я думаю, что все еще могу думать слишком последовательно (вероятно, поэтому я предпочитаю Async/Await
) .
Вам нужно вернуть значение из внешней функции getLocalDBInfo
function getLocalDBInfo(db) {
return new Promise((resolve, reject) => {
db.info()
.then(info => resolve(info))
.catch(err => reject(err))
})
}
getLocalDBInfo
генерирует промис, прикрепляет к нему обратный вызов, а затем возвращает undefined
. Он не возвращает выполненное обещание, и вы не можете ждать undefined
(ну, вы можете, но это ничего не сделает).
Вам нужно изменить getLocalDBInfo
на return
обещание.
Кроме того, почему у вас есть блок then
с подписью info => info
? Все, что нужно сделать, это развернуть асинхронное значение, а затем снова его обернуть. Вы можете полностью опустить обратный вызов then
.
Точно так же вы уверены, что вам нужно обернуть вызов db.info
в try/catch? Интересно, не собираетесь ли вы вместо этого использовать здесь promise.catch
. Конструкция try/catch захватывает отказы обещаний только тогда, когда awaiting
выражение.
Спасибо за ответ, который был полезен и в конечном итоге привел к тому, что у меня все заработало. Простите, что, несомненно, является очень простым, смущающе простым вопросом, но я думал, что цель синтаксиса .then
состоит в том, чтобы дождаться разрешенного обещания, а затем что-то сделать с этим результатом. Затем я рассудил, очевидно, ошибочно, что если я поместил оператор return
в обратный вызов .then
, он вернет результат обещания (т.е. info
). Можете ли вы указать мне на это мышление? Я знаю, что что-то упускаю, но не могу понять, что это может быть.
@robertsmith Итак, когда обещание разрешается со значением, .then
отображает это значение в другое обещание. Но вам не нужно сопоставлять значение, вы можете просто дождаться обещания. Вы понимаете, что я имею в виду?
Да, я верю, что знаю. В этом есть смысл. Кажется, я делал дважды то, что нужно было сделать только один раз. Правильный? Извините, но еще один вопрос: если это сопоставляется с другим обещанием, какой вред будет в возврате этого обещания (кроме неэффективности, конечно)? Это новое обещание, которое я собирался вернуть return info
? Я не понимаю, как это могло быть, потому что это не сработало так, как у меня было. Еще раз спасибо за ваше время и помощь.
getLocalDBInfo
не помечен как асинхронный, плюс вам действительно нужноreturn
что-то вродеreturn await db.info();