Как получить доступ к запрашиваемому телу из другой функции с помощью async / await? - PullRequest
0 голосов
/ 02 октября 2018

извините за общее название.Я довольно новичок в nodejs, а также в идее async / await.

Итак, у меня есть экспресс-приложение, которое делает HTTP-запрос get в качестве функции обратного вызова.Функция обратного вызова получает объект body и возвращает его функции getBody.Но когда я пытаюсь присвоить getBody переменной, она возвращает undefined.

Да, я знаю.Функция getBody возвращает тело до того, как тело будет заполнено данными, но я просто не знаю, как написать метод получения для этого объекта тела.Поэтому мой вопрос заключается в том, как я могу одновременно выполнить запрос 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 голосов
/ 02 октября 2018

Хорошо, @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.');
});

Надеюсь, что поможет!

0 голосов
/ 02 октября 2018

await и async должны использоваться с обещанием, этот метод не может вернуть данные.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 не отправит ответ клиенту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...