Я следовал нескольким руководствам о том, как правильно ожидать данные из моей функции ListFile(). Я записал вывод на консоль в ListFile(), поэтому знаю, что данные верны. Когда я пытаюсь дождаться завершения функции и регистрации данных, я получаю один из двух результатов при экспериментировании с ожиданиями и обещаниями:
getData error: TypeError: undefined is not an object (evaluating 'response.json')
или
Promise {
"_U": 0,
"_V": 0,
"_W": null,
"_X": null,
}
Я создаю приложение React Native, и функция, которая вызывает ListFile(), содержит кучу других компонентов, которые отображаются, поэтому я не могу сделать всю функцию асинхронной. Не знаю, что еще здесь делать.
Вызывает ListFile()
const getData = async () => {
try {
const response = await ListFile();
const data = response.json();
console.info(data);
} catch (err) {
console.info("getData error: " + err);
}
}
getData(); //always returns getData error: TypeError: undefined is not an object (evaluating 'response.json')
СписокФайл()
async function ListFile() {
// Reference Firebase Container
var filesInStorageList = [];
let content = [];
const listRef = ref(fbStorage, filePath);
console.info("Listing Files");
// List all files in container
listAll(listRef)
.then((res) => {
res.prefixes.forEach((folderRef) => {
// All the prefixes under listRef.
// You may call listAll() recursively on them.
console.info(res);
});
res.items.forEach((itemRef) => {
// All the items under listRef.
let fileInStorage = itemRef["_location"]["path_"].slice(filePath.length);
filesInStorageList.push(fileInStorage);
// CORRECT DATA IS LOGGED console.info("Pushing " + fileInStorage);
// CORRECT DATA IS LOGGED console.info(filesInStorageList);
});
return filesInStorageList;
}).catch((error) => {
// Uh-oh, an error occurred!
console.info("ListFile - ERROR");
});
}
Вы смешиваете async/await и Promises. Хотя они служат схожим целям, обычно они используются по отдельности, чтобы избежать подобных ситуаций, когда они используются вместе, а затем создают неожиданные результаты, если не знать, на что обращать внимание.
Вы аннотируете свою функцию ListFile
с помощью async
, что означает, что она ожидает где-то найти await
. Вместо этого вы используете основанные на промисах .then
и .catch
.
Чтобы преобразовать ваш код, вы можете изменить его на это:
async function ListFile() {
// Reference Firebase Container
var filesInStorageList = [];
let content = [];
const listRef = ref(fbStorage, filePath);
console.info("Listing Files");
// List all files in container
try {
const res = await listAll(listRef);
//...do your forEach loops
return filesInStorageList;
} catch(err) {
//handle your error
}
}
Чтобы уточнить и убедиться, что я понимаю, должен ли я не вносить никаких изменений в getData? Когда я оставляю все как есть, ответ остается неопределенным.
Что вы имеете в виду под «ответ остается неопределенным»? Нет, не обязательно менять. Но имейте в виду, что, как написано в вашем вопросе, он не возвращает значение и не устанавливает какое-либо состояние.
Вы должны добавить return
к методу listAll
, чтобы возвращать его значение при вызове из getData()
. См. пример кода ниже:
const getData = async () => {
try {
ListFile()
.then((response) => {
// do something here.
console.info(response);
});
} catch (err) {
console.info("getData error: " + err);
}
}
getData();
async function ListFile() {
// Reference Firebase Container
var filesInStorageList = [];
let content = [];
const filePath = "test/";
const listRef = ref(storage, filePath);
// List all files in container
return listAll(listRef)
.then((res) => {
res.prefixes.forEach((folderRef) => {
// All the prefixes under listRef.
// You may call listAll() recursively on them.
console.info(res);
});
res.items.forEach((itemRef) => {
// All the items under listRef.
let fileInStorage = itemRef["_location"]["path_"].slice(filePath.length);
filesInStorageList.push(fileInStorage);
// CORRECT DATA IS LOGGED console.info("Pushing " + fileInStorage);
// CORRECT DATA IS LOGGED console.info(filesInStorageList);
// console.info(filesInStorageList);
});
return filesInStorageList;
}).catch((error) => {
// Uh-oh, an error occurred!
console.info(error);
});
}
Кроме того, как заявил @jnpdx, вы должны использовать .then и .catch на основе Promise на своем ListFile()
Является ли return filesInStorageList;
правильным, хотя теперь возвращается весь listAll(listRef)?
@Поли, да. есть также return filesInStorageList;
, который затем вернет fileInStorage
, помещенный в массив filesInStorageList
. Это один из обходных путей для вашего варианта использования.
Это сработало, я также обновил свой файл getData. Спасибо!