【问题标题】:Using Promises in Express在 Express 中使用 Promise
【发布时间】:2019-08-01 11:19:59
【问题描述】:

我想要一个应用程序,其中用户键入地址作为查询字符串,然后接收该位置的天气作为 json 对象。在天气检索部分,我使用 promises 来获取地址的经纬度,然后是天气。还有用于指定语言和单位的选项。

function getWeather(encodedAddress, units, language) {
    let geoKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXX';
    let geocodeURL = `http://www.mapquestapi.com/geocoding/v1/address?key=${geoKey}&location=${encodedAddress}`;

    return axios.get(geocodeURL).then(({data}) => {
        if (((data.results[0].locations[0].geocodeQualityCode.substring(2)).match(/X/g) || []).length > 1) {
            throw new Error('Unable to find that address')
        }
        const locationInfo = data.results[0].locations[0];
        const lat = locationInfo.latLng.lat;
        const lng = locationInfo.latLng.lng;

        console.log('Here\'s the weather for: ', locationInfo.street, locationInfo.adminArea5,
                                locationInfo.adminArea4, locationInfo.adminArea1, 
                                locationInfo.postalCode);
        
        const weatherKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
        
        units = units ? `units=${units}` : 'auto';
        language = language ? `lang=${language}` :  'lang=en';
        
        const weatherURL = `https://api.darksky.net/forecast/${weatherKey}/${lat},${lng}?${units}&${language}`;
        return axios.get(weatherURL);

    }).then(({data}) => {
        const tempInfo = data.currently;
        const temp = tempInfo.temperature;
        const apparentTemp = tempInfo.apparentTemperature;
        const summary = tempInfo.summary;

        console.log(`It's currently ${temp} degrees and feels like ${apparentTemp} degrees. \nThe local summary is: ${summary}.`);

        return data.currently;
        
    }).catch(error => {
        if (error.code === 'ENOTFOUND') {
            throw new Error('Could not connect to MapRequest server');
        } else {
            throw new Error(error.message);
        }
    });
};

在我的 app.js 中有

app.get('/weather', (req, res, next) => {
    if (!req.query.address) {
        return res.send({
            error: 'You must provide an address!'
        })
    }

    forecast.getWeather(req.query.address).then(function(data) {
         res.send(data);
    });
    next();
});

我在浏览器中收到Cannot read property then of undefined 错误。我在想那是因为当发送响应时,承诺还没有解决。 app.get 基于 express 文档中的内容,所以我认为这可能与我的 getWeather 函数有关。如何等待 promise 解决然后执行所有操作?

【问题讨论】:

  • 为getWeather函数添加你的导出和导入,你是直接导出函数吗?
  • 为什么then(({data})为什么不then((data) => {...})
  • 好像forecast.getWeather 实际上并没有使用function getWeather - 这可能吗? function getWeather 怎么变成 forecast.getWether ... 还有 I'm thinking that's because when the response is sent the promise hasn't resolved 不,promise 总是有一个 .then 方法,因为这就是 promise 的工作原理
  • @JaromandaX 可能是错误的导出和导入语句。
  • forecast.getWeather 是一个函数 - 否则错误将是别的东西:p @AZ_

标签: javascript node.js express promise


【解决方案1】:

您在请求数据后立即调用 Express 回调,此处:

forecast.getWeather(req.query.address).then(function(data) {
    res.send(data);
});
next();

试试这个:

forecast.getWeather(req.query.address).then(function(data) {
    res.send(data);
    next();
});

顺便说一句,我建议catch-ing 你的 Express 路由器中的错误并将其传递给 Express 错误处理程序,这样 HTTP 请求将正确失败,而不仅仅是挂起:

forecast.getWeather(req.query.address).then(function(data) {
    res.send(data);
    next();
}).catch(next);

最后一行是}).catch(err => next(err));的简写。

【讨论】:

  • 我什至没有发现 next()。而且我不确定他是否需要它。他没有实现中间件(不需要直接访问请求或响应
【解决方案2】:

您可以使用PromiseBluebird npm 包作为promise。

试试这个。

const Promise = require('promise')

function getWeather(encodedAddress, units, language) {
    return new Promise((resolve, reject) => {
        let geoKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXX';
        let geocodeURL = `http://www.mapquestapi.com/geocoding/v1/address?key=${geoKey}&location=${encodedAddress}`;

    axios.get(geocodeURL).then(({ data }) => {
        if (((data.results[0].locations[0].geocodeQualityCode.substring(2)).match(/X/g) || []).length > 1) {
            throw new Error('Unable to find that address')
        }
        const locationInfo = data.results[0].locations[0];
        const lat = locationInfo.latLng.lat;
        const lng = locationInfo.latLng.lng;

        console.log('Here\'s the weather for: ', locationInfo.street, locationInfo.adminArea5,
            locationInfo.adminArea4, locationInfo.adminArea1,
            locationInfo.postalCode);

        const weatherKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';

        units = units ? `units=${units}` : 'auto';
        language = language ? `lang=${language}` : 'lang=en';

        const weatherURL = `https://api.darksky.net/forecast/${weatherKey}/${lat},${lng}?${units}&${language}`;
        axios.get(weatherURL).then(resolve).catch(reject);

    }).then(({ data }) => {
        const tempInfo = data.currently;
        const temp = tempInfo.temperature;
        const apparentTemp = tempInfo.apparentTemperature;
        const summary = tempInfo.summary;

        console.log(`It's currently ${temp} degrees and feels like ${apparentTemp} degrees. \nThe local summary is: ${summary}.`);

        resolve(data.currently);

    }).catch(error => {
        if (error.code === 'ENOTFOUND') {
            reject(new Error('Could not connect to MapRequest server'));
        } else {
            reject(Error(error.message));
        }
    });
});
};

【讨论】:

  • 当问题不是缺少 Promise 时,为什么 OP 需要一个 Promise 库,它是返回 undefined 而不是 Promise 因此它没有 .then
猜你喜欢
  • 2017-10-08
  • 2016-05-04
  • 2014-12-15
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 1970-01-01
  • 2017-07-01
相关资源
最近更新 更多