Как вызвать вложенную выборку?

#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:

Вы не слишком далеки от истины, но:

  1. Ваш обработчик выполнения отладки вмешивается, заменяя значение выполнения из fetch на undefined (возвращаемое значение console.log ). Вы захотите удалить его.
  2. Не используйте 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 по моему вопросу?