首页 > 解决方案 > 使用请求承诺的 Node.js 嵌套回调不起作用

问题描述

我有一个非常简单的 nodejs/express API,它正在制作一个request.get()inside request.post()。我只是想 res.send 的响应正文request.get()

我尝试使用带有requestandrequest-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()最终应该return res.Results在我的getResults()函数中给出。

最令人困惑的部分是我需要那个奇怪的 if 语句submitSearch()googleMapsClient正确分配mapCenter,然后submitSearch()再次递归调用。我知道这是一个异步问题,我看过的无数线程和视频都没有涵盖这种特殊类型的案例。

标签: node.jspromisecallback

解决方案


我建议使用promise API .geocode(),然后你不要试图混合普通的回调和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 文档显示了这一点:

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

所以,当你初始化这样的东西以使用内置的 Promise 时,你可能需要告诉它使用哪个 Promise 实现。


推荐阅读