What is the best way to implement a nested fetch call?

I have a piece of code similar to the one below that is functioning properly:

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"))
);

My goal now is to use the Operation-Location header, which contains a URL address, to make a GET request and retrieve the final response from the body of this new request.

I have attempted the following code, but unfortunately, it is not working:

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"))
  );

When testing my code here, I encounter an error related to test1. However, in my Visual Studio, there are no compilation errors, even though the GET request is not executed. I have even tried to capture the error using the following line:

.catch((err) => console.log("odsPolicyRequestError" + err));

but it remains empty. I am unable to identify the issue and where I may have made an error.

Your assistance in resolving this matter would be greatly appreciated.

Update 1:

Here is the updated code based on the suggestion. However, I am still receiving "not started yet" as the output of my second call. It appears that the second call is initiated before the first one is completed.

 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); } );

Answer №1

You're close, but not quite there yet:

  1. Remove the debugging fulfillment handler that is replacing the fulfillment value from fetch with undefined (the return value of console.log).

  2. Avoid using the test1 variable and instead utilize the fulfillment value provided to the fulfillment handler (callback passed to .then).

You can try something like this:

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");
});

Keep in mind that this code does not handle the bodies of the responses. You may need to consider including the body of the second response at least.

Alternatively, if you can utilize an async function, the following code (inside an async function) uses await instead of .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");

Side note: Your use of the fetch API may lead to unexpected outcomes. fetch only rejects the promise on network errors, not HTTP errors. Make sure to explicitly check for success at the HTTP level, as demonstrated below:

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");
});

You can also consider using a fetch wrapper that handles the ok check for you.


Side note 2: Always ensure you handle promise rejection or pass the promise chain back to the caller for error checking. Your current code does not address this important aspect.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Zod Entry using standard encryption key

I'm attempting to define an object type in zod that looks like this: { default: string, [string]: string, } I've experimented with combining z.object and z.record using z.union, but the validation results are not as expected. const Local ...

Angular does not support the functionality of having multiple material paginations within a single component

I am currently working on creating a component that contains two dataTables, each with a different dataSource. However, I am facing an issue where my Tables are not visible immediately after the component is loaded due to the *ngIf directive being used. Be ...

What is the most efficient way to simultaneously check multiple variables for undefined values?

Before executing my code, I need to ensure that none of the variables in a given list are undefined. In the code snippet below, there are 4 variables with uncertain values. While I can manually check variables a and b to satisfy TypeScript's requirem ...

Switch from using fetch to utilizing axios for making API requests

I used fetch for a 'get' request, but now I want to switch to axios. Can someone please help me convert this code to use axios instead? More details: I am fetching an image and using the blob method to display it to the user. I would like to ach ...

The 'connectedCallback' property is not found in the 'HTMLElement' type

After taking a break from my project for a year, I came back to find that certain code which used to work is now causing issues: interface HTMLElement { attributeChangedCallback(attributeName: string, oldValue: string, newValue: string): void; con ...

The parameter type 'string | null' cannot be assigned to the argument type 'string'. The type 'null' is not compatible with the type 'string'.ts(2345)

Issue: The parameter type 'string | null' is not compatible with the expected type 'string'. The value 'null' is not a valid string.ts(2345) Error on Line: this.setSession(res.body._id, res.headers.get('x-access-token&ap ...

Exploring the Mechanism Behind the Successful String Interpolation of a Variable Imported in my Angular 2 Application

After making some modifications to my Angular 2 application, I encountered a situation where something started functioning properly sooner than I expected. This has left me puzzled about why it's working in its current state. Specifically, I have an a ...

What is the correct way to handle the return value of an useAsyncData function in Nuxt 3?

How can I display the retrieved 'data' from a useAsyncData function that fetches information from a pinia store? <script setup lang="ts"> import { useSale } from "~/stores/sale"; const saleStore = useSale(); const { da ...

Variations in key options based on specific situations

Is it possible to make certain keys required in Typescript depending on the circumstances? For instance interface IDog { name: string; weight: number; } class Retriever implements IDog { name = "Dug"; weight = 70; public updateAttribute(props ...

Utilizing custom types in React with TypeScript and Prop-Types

Currently, I am working with a string type literal that looks like this: type MyType = 'str1' | 'str2' | 'str3'. I need one of my props to only accept this specific type, but I'm struggling to specify this in PropTypes. ...

struggling with configuring dependency injection in NestJS and TypeORM

Struggling with integrating nestjs and typeorm for a simple CRUD application, specifically facing issues with dependency injection. Attempting to modularize the database setup code and import it. Encountering this error message: [ExceptionHandler] Nest ...

Angular 5 APP_INITIALIZER: Provider parse error - Cyclic dependency instantiation not possible

I am utilizing the APP_INITIALIZER token to execute a task upon page load before my Angular application is initialized. The service responsible for this functionality relies on another service located within my CoreModule. The issue at hand seems to be ab ...

There was an error linking the module "electron_common_features" which caused the Electron react test to fail

I recently developed a React Electron application using the electron-react-boilerplate template. I also added the @electron/remote package and made changes to the test case. However, upon running the command npm test, an error message stating No such modul ...

Modify information in formArray

Let's take a look at this setup I have: Model: export class MapDetailModel{ id: number; lat: number; lon: number; alt: number; long: number; angle: number; distance?: number; pendenza?: number; } Html: <div clas ...

Instructions for creating a function that can receive an array of objects containing a particular data type for the value associated with the key K

Seeking guidance on how to define a specific signature for a function that accepts an array of objects and 3 column names as input: function customFunction<T, K extends keyof T>( dataset: T[], propertyOne: K, propertyTwo: K, propertyThird: K ...

Could this be a problem within my recursive function?

Struggling to iterate through a stack of HTML Elements, I attempted to write a recursive function with no success. In the code snippet below, I'm facing challenges in returning a value from an if statement and ultimately from the function itself. Wh ...

How can this be happening? It's expected that items will be printed, but for some reason

I'm struggling to figure out why the console.logs aren't showing up. import { GenericRepository, getGenericRepository } from '../src/database/repository/GenericRepository'; import { start, stop } from '../src/index'; import r ...

Contrast the differences between arrays and inserting data into specific index positions

In this scenario, I have two arrays structured as follows: arr1=[{room_no:1,bed_no:'1A'}, {room_no:1,bed_no:'1B'}, {room_no:2,bed_no:'2A'}, {room_no:3,bed_no:'3A'}, {room_no:3,bed_no:'3B ...

TypeScript Error 2304: Element 'div' is nowhere to be found - CRA TypeScript Template

I'm experiencing a problem in VSCode while working on the default create-react-app my-app --template typescript project. It seems to not recognize any HTML elements, as I keep getting the error cannot find name xxx, where 'xxx' represents th ...

NextJS 13 causes tailwind to malfunction when route group is utilized

I've encountered an issue in my NextJS 13 application where Tailwind classes are no longer being applied after moving page.tsx/layout.tsx from the root directory to a (main) directory within the root. I suspect that there may be a configuration that i ...