#javascript #reactjs #loops #promise #fetch
#javascript #reactjs #циклы #обещание #выборка
Вопрос:
Мне нужно отредактировать ранее сохраненные сообщения, содержащие вложения. В функции редактирования пользователь должен иметь возможность редактировать заголовок или текст сообщения, заменять существующие вложения или удалять вложения.
Сценарий: пользователь внес изменения в текст сообщения, заменил одно вложение и удалил 2 вложения и нажал Сохранить. При нажатии кнопки сохранения должны выполняться следующие действия
- Сначала заменяйте и удаляйте асинхронные вызовы API
- Если замена и удаление выполнены успешно, то вызов api для сохранения изменений в тексте
Вот где я нахожусь..
.then
Promise.all
in replace
и delete
выполняется до завершения обещания цикла, в результате чего внешнее обещание (in handleSave
) всегда получает разрешенное обещание.
deleteData
и replaceData
являются массивами, содержащими данные, подлежащие замене / удалению
const delete = () => {
if (deleteData.length > 0) {
return Promise.all([
deleteData.map(data => fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error('Delete Failed');
}
})
),
]).then(() => Promise.resolve('Deleted'));
}
return Promise.resolve('Nothing to delete');
};
const replace = () => {
if (replaceData.length > 0) {
return Promise.all([
replaceData.map(data => fetch(url)
.then((response) => {
if (response.status === 400) {
response.text().then((error) => {
const errorObject = JSON.parse(error);
throw new Error(error);
});
} else if (!response.ok) {
throw new Error('Update Failed');
}
})
),
]).then(() => Promise.resolve('Replaced'));
}
return Promise.resolve('Nothing to replace');
};
const saveMessage = () => {
fetch(saveUrl)
.then((response) => {
if (response.status === 400) {
response.text().then((error) => {
const errorObject = JSON.parse(error);
throw new Error(error);
});
} else if (!response.ok) {
throw new Error('Save Failed');
}
});
}
const handleSave = () => {
Promise.all([replace, delete])
.then(() => {
saveMessage();
}).catch((e) => {
//Catch action
})
}
Комментарии:
1. Ваш
save
ничего не возвращает, вы, вероятно, хотитеreturn
выполнить вызов выборки, чтобы его можно было перехватить ниже в handleSave
Ответ №1:
В ваш Promise.all
s вы в настоящее время передаете массив, содержащий один элемент, где этот элемент представляет собой массив обещаний. В результате Promise.all
проблема немедленно устраняется.
Promise.all
Вместо этого передайте массив обещаний, то есть просто .map
нет [data.map(...)]
. Изменить:
return Promise.all([
deleteData.map(data => fetch(url)
Для
return Promise.all(
deleteData.map(data => fetch(url)
и
return Promise.all([
replaceData.map(data => fetch(url)
Для
return Promise.all(
replaceData.map(data => fetch(url)
Кроме того, внутри replace
он не возвращает внутреннее .text
обещание при возникновении ошибки 400, поэтому его сопоставление Promise.all
не будет отклоняться, когда вы этого захотите. Изменить:
if (response.status === 400) {
response.text().then((error) => {
const errorObject = JSON.parse(error);
throw new Error(error);
});
Для
if (response.status === 400) {
return response.json().then((error) => {
throw new Error(error);
});
(обратите внимание, что вы можете использовать .json()
вместо JSON.parse
)
Кроме того, чтобы ваши saveMessage
ошибки обрабатывались в catch
, вы также должны возвращать каждое из его обещаний:
const saveMessage = () => {
return fetch(saveUrl)
.then((response) => {
if (response.status === 400) {
return response.json().then((error) => {
throw new Error(error);
});
} else if (!response.ok) {
throw new Error('Save Failed');
}
});
};
Комментарии:
1. Спасибо, но проблема не в этом.. Проблема в том, что циклы в replace и delete работают не так, как ожидалось. Я предпочитаю сохранить .text(), потому что, если ответ пуст.json() завершается с ошибкой
2. Это определенно, по крайней мере, одна часть проблемы. Можете ли вы показать, где вы определяете
deleteData
,replaceData
,replace
,delete
?3. deleteData и replaceData — это массивы, содержащие данные, подлежащие замене / удалению
4. Я вижу проблему, вы передаете массив массивов
Promise.all
вместо массива обещаний.5. Вы уверены, что добавили
return
? То естьreturn response.text()
или.json()
вместо простоresponse.text()
или.json()
?