【问题标题】:Node.js nested callbacks using request-promise not working使用请求承诺的 Node.js 嵌套回调不起作用
【发布时间】:2019-09-14 02:41:24
【问题描述】:

我有一个非常简单的 nodejs/express API,它在 request.post() 中创建了一个 request.get()。我只是想重新发送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()) 在我的rp.post() 调用中吐出我的return getResults(res.id) 语句,最终应该在我的getResults() 函数中给出return res.Results

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

【问题讨论】:

  • 呃,不要编辑您的问题以包含您的最终解决方案。这不是*的工作方式。问题仍然是问题。答案就在哪里。我们希望您的问题能够显示您提出的原始问题,这样这可以成为原始问题的持久参考,然后是对该问题的一个或多个答案。请编辑您的问题,使其恢复原状。
  • 注明。虽然@Akatsuki levi 的回答没有给我正确的结果。他的洞察力使我自己编辑代码以获得我需要的东西。如果我仍然接受他/她的回答可以吗?
  • 您可以添加自己的答案以显示您最终决定使用的内容(是的,您可以回答自己的问题)。我正在研究一个我认为比两者都更好的答案,如果您想稍等一下,因为使用 googleMaps 的 promise 接口和链式 promise 确实要简单得多,这样您就可以在一个地方处理所有错误。 Levi 的回答缺少很多错误处理。
  • 我现在发布了我的简化答案。

标签: node.js promise callback


【解决方案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 实现。

【讨论】:

  • 非常感谢@jfriend00。这解决了我的问题。
【解决方案2】:

欢迎来到 *! 而且,正如我在您的代码中看到的那样,您在设置函数之前调用 res.send 。 submitSearch 是在调用自己吗? 为方便起见,我会像这样重写代码:

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);
            })
        });
    }
})

【讨论】:

  • 我看到您正在重新发送来自geoCodeResponsegeoCodeResponse。我实际上再次调用submitSearch,因为我需要res.send 来自else 语句的post body。具体来说,我将发布到自定义域 设置 mapCentergoogleMapsClient
最近更新 更多