如何使用async / await从另一个函数访问请求的主体?

时间:2018-10-02 09:30:09

标签: node.js http express asynchronous promise

对不起,通用标题。我对nodejs以及异步/等待的想法很陌生。

因此,我有一个快速应用程序,它可以将HTTP get请求作为回调函数。回调函数获取主体对象,并将其返回给getBody函数。但是,当我尝试将getBody分配给变量时,它返回未定义的。

是的,我知道。 getBody函数在body填充数据之前返回body,但是我只是不知道如何为该body对象编写getter方法。因此,我的问题是,如何才能在全局范围内同时运行get请求和访问body对象,因此依赖于body对象的所有函数都可以运行而没有更多问题。

async function getBody (req, res, next) {
    let body = await makeRequest(req, res);
    return body; // THIS RETURNS UNDEFINED

}

router.get('/', getBody);

function makeRequest (req, res){

    let uri;

    let options = {
        uri: uri,
    };

    request(options,  function (error, response, body) {
        if (error){
            console.log('error:', error);
        } else {
            console.log('Success! statusCode:', response && response.statusCode);
            let jsonObject =  JSON.parse(body);

            return jsonObject;
        }
    });
}

我做了研究,但是我找不到有用的资源。预先感谢。

2 个答案:

答案 0 :(得分:3)

awaitasync应该与promise一起使用,这种方法不能返回数据。 return用于从同步方法返回值。

因此,您可以像这样从makeRequest方法返回承诺,

async function getBody(req, res, next) {
    let body = await makeRequest(req, res);
    return body; // NOW BODY IS NOT UNDEFINED, call next() or send response here
}

router.get('/', getBody);

function makeRequest(req, res) {
    return new Promise((resolve, reject) => {
        let uri;

        let options = {
            uri: uri,
        };

        request(options, function (error, response, body) {
            if (error) {
                console.log('error:', error);
                return reject(error);
            } else {
                console.log('Success! statusCode:', response && response.statusCode);
                let jsonObject = JSON.parse(body);

                return resolve(jsonObject);
            }
        });
    })
}

仅供参考,

let body = await makeRequest(req, next)

等于

makeRequest(req, next).then(body => { /* YOUR CODE HERE */ })

如果您不知道,则必须处理正文并发送响应,return body不会将响应发送给客户端。

答案 1 :(得分:2)

好的,@ JanithKasun在完全回答您原来的问题方面做得很好。这个答案的目的是扩大一点,以解决您在概念上没有明确提出的问题。

据我了解您的代码,您正在尝试根据到达应用程序处理程序的请求中的信息从第三方资源中获取一些数据。理想情况下,您希望以一种使代码更加可重用/可维护的方式来分离代码。我注意到有问题的代码实际上根本没有使用请求或响应对象 ,但我将假设您的getBody函数具有某种参数,可以帮助您构建它正在请求的URI。因此,为此:

// ./lib/get-body.js
const BASE_URI = 'https://example.com/search?q='
async function getBody (query) {
    let body = await makeRequest(query);
    return body;
}

function makeRequest(query) {
    return new Promise((resolve, reject) => {
        let uri = `${BASE_URI}{query}`; // results in something like 'https://example.com/search?q=cats'

        let options = {
            uri: uri,
        };

        // Note: removed console statements here to centralize error handling
        request(options, function (error, response, body) {
            if (error) {
                return reject(error);
            } else {
                let jsonObject = JSON.parse(body);
                return resolve(jsonObject);
            }
        });
    })
}
// export the top level function for reuse
module.exports = getBody;

现在,在您的路由代码中:

// ./index.js or wherever
const express = require('express');
const getBody = require('./lib/get-body');

//...whatever other setup...

app.get('/', async (req, res, next) => {
    const query = req.query.terms; // or whatever
    try {
      const body = await getBody(query);
      return res.send(body);
    } catch (e) {
        return next(e); // if you don't do this, process hangs forever on error
    }
});

// handle the errors. obviously you can do something smart like 
//  figure out the error code and send back something other than a 500 if appropriate. 
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send('I am Bender; please insert girder.');
});

希望有帮助!