Home > Software engineering >  Response doesn't wait for async function
Response doesn't wait for async function

Time:03-13

I found the aproach how to put the async function into a router endpoint and tried to implement it but not suceed. E.g. this link zellwk.com

The server sends only empty string instead of a huge string that is on snippet.host.

    async function downloadData(url) {
        const options = {
            'method': 'GET', 'url': url, 'headers': {}, formData: {}
        };
        let result = '';
        await request(options, function (error, response) {
            if (error) throw new Error(error);
            console.log(response.body)
            result = response.body
        });
        return {error: 0, text: result}
    }
    app.get('/token/:token', jsonParser, async function (req, res) {
        console.log(req.params.token) //Don't mind this token
        try {
            let message = await downloadData('https://snippet.host/xgsh/raw')
            res.send(message)
        } catch (e) {
            console.log(e);
            res.sendStatus(500);
        }
    });

How to make it wait for the download?

EDIT

I implemented node-fetch and got this: {"error":0,"text":{"size":0}} What did I wrong?

async function downloadData(url) {
    const result = await fetch(url)
    return {error: 0, text: result}
}

app.get('/token/:token', jsonParser, async function (req, res) {
    console.log(req.params.token)
    try {
        let message = await downloadData('https://snippet.host/xgsh/raw')
        res.send(message)
    } catch (e) {
        console.log(e);
        res.sendStatus(500);
    }
});

CodePudding user response:

You can only usefully await a promise.

request doesn't return a promise, it takes a callback function instead.

This is one of the reasons that request was deprecated two years ago.

Replace request with something which supports promises such as node-fetch, the native fetch that was added to Node.js recently, or axios.

CodePudding user response:

In case you must use request (eventhough it's deprecated); or in case you find a similar situation with a old function that doesn't return a promise; you can turn your request into a function that returns a promise.

Either write your own wrapper, in the form of

function requestPromise(options) {
  return new Promise( 
    (resolve,reject) => request(options, 
      (err,response) => if (err) reject(err) else resolve(response)));
}

or, given that request's callback is in the form of function(err,response), directly use util.promisify

async function xxxx(...) {
    try {
      ...
      let response = await util.promisify(request)(options);
      ...        
}

CodePudding user response:

Because request isn't actually an async function that returns a Promise, you can create your own async version of request.

function asyncRequest(options) {
    return new Promise((resolve, reject) => {
        request(options, (err, response) => {
            if (err) {
                reject(err)
            } else {
                resolve(response)
            }
        })
    })
}

Then in your project rewrite your downloadData function to be:

async function downloadData(url) {
  const options = {
    method: "GET",
    url: url,
    headers: {},
    formData: {},
  }

  const result = await asyncRequest(options)

  return { error: 0, text: result.body }
}

CodePudding user response:

in case of fetch call the response body need to be parsed first which you are missing.

async function downloadData(url) {
    const res = await fetch(url)
    if (res && res.status != 200)
        throw new Error("status code other than 200 received")
    let json = await res.json()
    return {error: 0, text: json}
}

app.get('/token/:token', async function (req, res) {
    console.log(req.params.token)
    try {
        let message = await downloadData('https://snippet.host/xgsh/raw')
        // let json = await  message.json()
        res.send(message)
    } catch (e) {
        console.log(e);
        res.sendStatus(500);
    }
});

i tried calling the api but every time it is returning 404 . so json cant be called in that case. but if 200 is returned then you call json and return that accordingly.

  • Related