1

I want to send an http request and return the result using typescript, before send the http request, I want to get the token from google chrome local storage and put the token into http header. This is my typescript code looks like:

api_post:<T>(url: string, data: any): Promise<T> => {
    chrome.storage.local.get("token", function (result:any) {
        return fetch(url, {
            method: 'POST',
            headers: {
                'Content-type': 'application/json',
                'x-access-token': result,
            },
            body: JSON.stringify(data),
        })
            .then(response => {
                if (!response.ok) {
                    throw new Error(response.statusText);
                }
                return response.json() as Promise<T>;
            });
    });  
},

the problem is the promise return from the inner of an async code block, this function shows error:

interface Promise<T>
Represents the completion of an asynchronous operation

A function whose declared type is neither 'void' nor 'any' must return a value.ts(2355)

what should I do to return the promise inside the chrome local storage get and make the code works?

2
  • 1
    I would recommend converting the arrow function into an async method, and using await statements instead of callbacks. First GET the token, then prepare the POST using the response from the GET, and then finally return the response from the POST. Commented Feb 13, 2022 at 7:27
  • 1
    return fetch(... is inside, and therefore belongs to function (result:any) {. Your api_post function has not return. But the declared return type is Promise<T> Commented Feb 13, 2022 at 7:37

3 Answers 3

2

I would use the Promise constructor. Then, resolve the final desired value in the chain, and reject any errors.

const api_post = <T>(url: string, data: any): Promise<T> => {
    return new Promise((resolve, reject) => {
        chrome.storage.local.get("token", function (result: any) {
            return fetch(url, {
                method: "POST",
                headers: {
                    "Content-type": "application/json",
                    "x-access-token": result,
                },
                body: JSON.stringify(data),
            }).then((response) => {
                if (!response.ok) {
                    reject(new Error(response.statusText));
                    return;
                }
                resolve(response.json() as Promise<T>);
            });
        });
    });
};
Sign up to request clarification or add additional context in comments.

Comments

1

To follow-up on my comment, you could do something like:

api_post: async (url: string, data: any): Promise<T> => {
    const { result } = await chrome.storage.local.get("token");
    const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-type': 'application/json',
                'x-access-token': result,
            },
            body: JSON.stringify(data),
        });
    return response;
},

Note: This is just to give you an idea of how you could refactor your method using async/await. This code will probably require some tweaking.

2 Comments

I do like this way at beginning of coding, but this will make all nest invoke function async. @Ross Gatih
@spark an async function is simply a function that always returns a Promise. You don't get around that Promise, your only choice is whether you write await api_post() or api_post().then(...)
1

Just throwing in another snippet, since OP seem to dislike async/await from Ross Gatih' answer and I don't like the new Promise antipattern from Jordan Wrights answer

const api_post = <T>(url: string, data: any): Promise<T> => {
  return chrome.storage.local.get("token")
    .then((result: any) => fetch(url, {
      method: "POST",
      headers: {
        "Content-type": "application/json",
        "x-access-token": result,
      },
      body: JSON.stringify(data),
    }))
    .then((response) => {
      if (!response.ok) {
        throw new Error(response.statusText);
      }
      return response.json();
    });
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.