#typescript #post #get #fetch
#typescript #Публикация #получить #выборка
Вопрос:
У меня есть код, подобный следующему, который работает:
const url = "https://something";
let data2 = JSON.stringify({ source: "https://someimage.jpg" });
const test1 = fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Ocp-Apim-Subscription-Key": "mykey",
},
body: data2,
}).then((res) =>
console.log("postHeaderResult" res.headers.get("Operation-Location"))
);
Теперь, что я хочу сделать, это использовать Operation-Location
заголовок, который является url
адресом, и отправить GET
запрос, а затем получить окончательный ответ из тела этого нового запроса.
Я пробовал следующий код, но он не работает:
const url = "https://something";
let data2 = JSON.stringify({ source: "https://someimage.jpg" });
const test1 = fetch(url_to_formRecognizer, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Ocp-Apim-Subscription-Key": "mykey",
},
body: data2,
})
.then((res) =>
console.log("postHeaderResult" res.headers.get("Operation-Location"))
)
.then((res1) =>
fetch(test1.headers.get("Operation-Location"), {
method: "GET",
headers: {
"Ocp-Apim-Subscription-Key": "34dd609bcb5742de91e8474f0e27e88e",
},
}).then((res1) => console.log("finalResult" res1 "simple"))
);
В то же время, если я попробую свой код здесь, я получу сообщение об test1
ошибке , но в моем visual studio
я не получаю никакой ошибки компиляции, хотя запрос get не выполняется.
Я даже попробовал следующую строку:
.catch((err) => console.log("odsPolicyRequestError" err));
чтобы зафиксировать ошибку, но она также пуста. Я не понимаю, в чем проблема и что я сделал не так.
Мы будем признательны за вашу помощь.
Обновление 1:
вот мой новый код, основанный на ответе. Но, наконец, я получаю «еще не запущен» в результате моего второго вызова. Кажется, что второй вызов начинается до того, как первый действительно завершен.
const url = "https://something";
let data2 = JSON.stringify({ source: documentUrl });
const res1 = await fetch(url, {
method: "POST",
headers: { 'Content-Type': 'application/json' , 'Ocp-Apim-Subscription-Key': apiKey},
body: data2
});
if (!res1.ok) {
console.log("postHeaderResult not okay first fetch" res1.status " on first fetch");
}
console.log("header is:" res1.headers.get("Operation-Location"), null);
const res2 = await fetch(res1.headers.get("Operation-Location"), {
method: "GET",
headers: {'Ocp-Apim-Subscription-Key' : apiKey }
}).then( res2 => { return res2.text(); }).then(text => { api.output("text" text, null); } );
Комментарии:
1. Ваш обработчик выполнения отладки вмешивается, заменяя значение выполнения из
fetch
наundefined
(возвращаемое значениеconsole.log
).2. попробуйте использовать async / await. . это будет намного чище и читабельно, и тогда будет легче отлаживать, читайте об этом легко
Ответ №1:
Вы не слишком далеки от истины, но:
- Ваш обработчик выполнения отладки вмешивается, заменяя значение выполнения из
fetch
наundefined
(возвращаемое значениеconsole.log
). Вы захотите удалить его. - Не используйте
test1
переменную. Значение выполнения предоставляется обработчику выполнения (ваш обратный вызов передается.then
). Это то, что вы хотите использовать.
Что-то вроде этого:
const url = "https://something";
let data2 = JSON.stringify({ source: 'https://someimage.jpg'});
fetch(url_to_formRecognizer, {
method: "POST",
headers: { 'Content-Type': 'application/json' , 'Ocp-Apim-Subscription-Key': 'mykey'},
body: data2
}).then(res1 => fetch(res1.headers.get("Operation-Location"), {
method: "GET",
headers: {'Ocp-Apim-Subscription-Key' : '34dd609bcb5742de91e8474f0e27e88e' }})
).then(res2 => {
console.log("finalResult" res2 "simple");
});
Но обратите внимание, что это не использует тело ни первого ответа, ни второго. Похоже, вам может не понадобиться тело первого, но я предполагаю, что вам нужно, по крайней мере, тело второго.
Или, если вы можете использовать async
функцию, этот код (в async
функции) может использовать await
вместо .then
:
const url = "https://something";
let data2 = JSON.stringify({ source: 'https://someimage.jpg'});
const res1 = await fetch(url_to_formRecognizer, {
method: "POST",
headers: { 'Content-Type': 'application/json' , 'Ocp-Apim-Subscription-Key': 'mykey'},
body: data2
});
if (!res1.ok) {
throw new Error("HTTP error " res1.status " on first fetch");
}
const res2 = await fetch(res1.headers.get("Operation-Location"), {
method: "GET",
headers: {'Ocp-Apim-Subscription-Key' : '34dd609bcb5742de91e8474f0e27e88e' }
});
if (!res2.ok) {
throw new Error("HTTP error " res2.status " on second fetch");
}
console.log("finalResult" res2 "simple");
Примечание: ваш код становится жертвой некоторой путаницы в fetch
API (я пишу об этом здесь). fetch
отклоняет свое обещание только при сетевой ошибке, а не при ошибке HTTP. Вам нужно проверить, что все работает на уровне HTTP явно. Вот как вы могли бы это сделать:
const url = "https://something";
let data2 = JSON.stringify({ source: 'https://someimage.jpg'});
fetch(url_to_formRecognizer, {
method: "POST",
headers: { 'Content-Type': 'application/json' , 'Ocp-Apim-Subscription-Key': 'mykey'},
body: data2
}).then(res1 => {
if (!res1.ok) {
throw new Error("HTTP error " res1.status " on first fetch");
}
return fetch(res1.headers.get("Operation-Location"), {
method: "GET",
headers: {'Ocp-Apim-Subscription-Key' : '34dd609bcb5742de91e8474f0e27e88e' }
});
}).then(res2 => {
if (!res2.ok) {
throw new Error("HTTP error " res2.status " on second fetch");
}
console.log("finalResult" res2 "simple");
});
(Или используйте fetch
оболочку, которая выполняет ok
проверку за вас, как я описываю в этом связанном сообщении в блоге.)
Примечание 2. Важно всегда либо обрабатывать отклонение обещания (в данном случае, вероятно, с a .catch
в конце), либо передавать цепочку обещаний обратно вызывающему, чтобы вызывающий мог проверить ее. Похоже, что ваш код не выполняет ни того, ни другого.
Комментарии:
1. Большое спасибо за ваш полный ответ и извините, если я задавал (и все еще задаю) глупые вопросы. Прошло всего 2-3 недели, как я начал программировать на typescript. Не могли бы вы сказать мне, как я могу получить тело res2? Я пробовал
res2.status
, и все в порядке, и 200, что означает, что все вроде бы в порядке, но ни один изres2.text
,res2
, иres2.body
возвращает ожидаемый ответ. Я просто получаю объекты или тексты, которые не имеют значения.2. @user13578 — Не беспокойтесь! Вы читаете тело, используя один из методов объекта ответа, который это делает, подробнее здесь . Например, если вы хотите, чтобы это было как текст, вы бы вызвали
text
метод и дождались выполнения обещания, которое он возвращает.3. Но когда я использую text(), я получаю
text() { return consumeBody.call(this).then(function (buffer) { return buffer.toString(); }); }
4. @user13578 — Как я уже говорил выше, вам нужно дождаться выполнения обещания. Например: .
.then(res2 => { if (!res2.ok) { throw new Error(/*...*/); } return res2.text(); }).then(text => { /* use the text here */ })
5. Еще раз большое спасибо. Теперь я получаю другую ошибку. Не могли бы вы посмотреть Обновление 1 по моему вопросу?