使用请求承诺的Node.js嵌套回调不起作用

时间:2019-09-13 16:40:33

标签: node.js promise callback

我有一个非常简单的nodejs / express API,它在request.get()内创建一个request.post()。我只想重新发送request.get()的响应正文。

我尝试使用带有requestrequest-promise... .then()方法的简单回调函数无济于事。

const request = require('request')
const rp = require('request-promise')

app.get("/", (req, res) => {
    var mapCenter
    var address = "user query"

    res.send(submitSearch());

    function submitSearch() {
        if (!mapCenter || !mapCenter.lat) {
            googleMapsClient.geocode({
                address: address,
            }, function(err, res) {
                if (!err) {
                    mapCenter = {lat:res.lat, lng:res.lng };

                    submitSearch();
                }
            });
        } else {
            var parameters = {
                uri: domain,
                form: {
                    latitude: mapCenter.lat,
                    longitude: mapCenter.
                },
                json: true
            }
            rp.post(parameters).then(function(res) {
                return getResults(res.id)
             })
        }
    }

    function getResults(id) {
        rp.get(domain+ id).then(function(res) {
            return res.Results;
         })

    }
})


app.get()函数中,我希望我的res.send(submitSearch())return getResults(res.id)调用中吐出rp.post()语句,该语句最终应在我的{ {1}}功能。

最令人困惑的部分是,我需要return res.Results中用于getResults()的怪异if语句来正确分配submitSearch(),然后再次递归调用googleMapsClient。我了解这是一个异步问题,我看过的无数线程和视频都没有涉及这种特殊情况。

2 个答案:

答案 0 :(得分:1)

我建议为.geocode()使用Promise API,这样您就不会尝试混合使用简单的回调和Promise。这不仅可以简化您的代码,还可以使强大的错误处理变得更加简单。到目前为止,我在这里看到的所有建议都缺少各种错误处理。我也看不出您为什么需要在此处递归调用自己的任何原因。

const rp = require('request-promise');

app.get("/", (req, res) => {
    let address = "user query";

    // use promise interface for geocode
    googleMapsClient.geocode({address}).asPromise().then(response => {
        return {lat: response.lat, lng: response.lng };
    }).then(mapCenter => {
        const parameters = {
            uri: domain,
            form: {
                latitude: mapCenter.lat,
                longitude: mapCenter.lng
            },
            json: true
        };
        return rp.post(parameters);        
    }).then(id => {
        return rp.get(domain+ id).then(res => res.Results);
    }).then(results => {
        res.send(results);
    }).catch(err => {
        // decide what to do here if there's an error
        console.log(err);
        res.sendStatus(500);
    });
});

注意,Google doc on using promises显示如下:

const googleMapsClient = require('@google/maps').createClient({
  key: 'your API key here',
  Promise: Promise
});

因此,可能在初始化此类内容以使用内置Promise时需要告诉它使用哪个Promise实现。

答案 1 :(得分:0)

欢迎来到StackOverflow! 而且,正如我在您的代码上看到的那样,您在设置函数之前先调用res.send。 然后,commitSearch正在调用自身? 为方便起见,我将像这样重写代码:

const request = require('request')
const rp = require('request-promise')

app.get("/", (req, res) => {
    var mapCenter;
    var address = "user query";

    if (!mapCenter || !mapCenter.lat) {
        googleMapsClient.geocode({
            address: address,
        }, function(err, geocodeResponse) {
            if (!err) {
                mapCenter = {lat:res.lat, lng:res.lng };
                res.send(geocodeResponse);
            } else {
                throw err; // throw the error if isn't a assert.
            }
        });
    } else {
        var parameters = {
            uri: domain,
            form: {
                latitude: mapCenter.lat,
                longitude: mapCenter.lng
            },
            json: true
        };
        rp.post(parameters).then(function() {
            rp.get(domain+ id).then(function(reqPromiseRes) {
                res.send(geocodeResponse);
            })
        });
    }
})