徒然なるままに

現在、海外にWebエンジニアになるべくカナダのカレッジに通い中。現地の生活やプログラミング、感じたことを気ままに書きます。

天気予報アプリ(express無し)の実装

はじめに

はじめたのブログ投稿になります。現在、海外でwebエンジニアになるべくカナダのバンクーバのカレッジに通っています。勉強した内容や、カナダでの生活を記事にしていこうと思いますので、どうぞよろしくお願いいたします。

概略

この記事ではUdemyのThe Complete Node.js Developer Course(3rd Edition)のSection6~9の内容を簡単にまとめました。

ここでは、APIを取得する方法とjsonで渡された値の取得方法を学びました。

Topic

  • Callback関数
  • Fetch
  • json
  • コマンド引数
  • module(import/export)
  • 分割代入

使用ライブラリ

  • request (簡単にhttpを作成するためのライブラリ)

https://www.npmjs.com/package/request

使用API

実装

// app.js

// utilsをimport(nodejsはimportではなく、requireでモジュールを取得する)
const geocode = require('./utils/geocode');
const forecast = require('./utils/forecast');

// コマンドから渡された引数を格納する
const addres = process.argv[2];

// 引数が渡されなかったら、エラーを返す。
if(!address) {
    return console.log('please provide an address')
}
// geocodeを実行し、エラーがない場合、latitude,longitude,loactionを取得し、forecastに値を渡す。

geocode(address, (error, {latitude, longitude, location})=> {
    if(error){
        return console.log(error);
    }
    
    // geocodeから渡された、latitudeとlongitudeをもとに天気予報と降水確率を返す。
    
    forecast(latitude, longitude, (error, forecastData)=>{
        if(error) {
            return console.log(error);
        }
        console.log(location);
        console.log(forecastData);
    })
})
// geocode.js

const request = require('request')

// importしたgeocode()を呼び出す。addressにはコマンド引数が渡される。

const geocode = (address, callback) => {
    //mapboxをfetchする。
    const url = 'https://api.mapbox.com/geocoding/v5/mapbox.places/'+  encodeURIComponent(address) + '.json?access_token=pk.eyJ1IjoidGd3IiwiYSI6ImNqdXBsN3ZlOTNiM3k0M252MzA1ZzY2NTkifQ.ucwg_oXHd7KDVTHgSufvTQ';
    
    // urlが正しく、json型で返されているかを判定する。
    
    request({url: url, json: true}, (error,{body})=>{
    
        // Urlが不正な場合、errorを返す
        
        if(error){
            callback('Unable to connect location service', undefined);
            
        // body.featuresに値がない場合、エラーを返す
        
        } else if(body.features.length === 0) {
            callback('unable to find your location', undefined);
            
        // 正常に値が返ってきた場合、latitude, longitude, locationを返す
        
        } else {
            callback(undifined, {
                latitude: body.features[0].center[1];
                longitude: body.feature[0].center[0],
                location: body.features[0].place_name
            })
        }
    })
}
// forecast.js

const request = require('request')

const forecast = (latitude, longitude, callback) => {
    const url = `https://api.darksky.net/forecast/cc390e4b8d3d1951f092c99243ae915d/${latitude},${longitude}?units=si`;
    
    //渡されたurlが正しく、json型で返ってきた場合、天気予報と降水確率を返す。
    
    request({url, json: true},(error, { body })=>{
        if(error) {
            callback('unable to connect service', undefined);)
        } else if (body.error) {
            callback('unable to find location', undefined)
        } else {
            callback(undefined, `${body.daily.summary}, ${body.daily.data[0].precipProbablity}%`)
        }
    })
}

module.exports = forecast;

mapbox api (ここではcenterの緯度経緯度を取得)

features: [
{
id: "place.9391334652012190",
type: "Feature",
place_type: [
"place"
],
relevance: 1,
properties: {
wikidata: "Q100"
},
text: "Boston",
place_name: "Boston, Massachusetts, United States",
bbox: [
-71.1255750165112,
42.3196059806256,
-70.9860500028801,
42.3974009328397
],
center: [
-71.0596,
42.3605
],
geometry: {
type: "Point",
coordinates: [
-71.0596,
42.3605
]
},
context: [
{
id: "region.6776276020561540",
short_code: "US-MA",
wikidata: "Q771",
text: "Massachusetts"
},
{
id: "country.9053006287256050",
short_code: "us",
wikidata: "Q30",
text: "United States"
}
]
},

darksky api (mapboxから取得した緯度経度をもとにdaily.sammaryとdaily.data[0]. precipProbabilityを取得)

実際、日々の生活でみるデータのやり取りが、このようなフォーマットで行われています。瞬時にデータのやり取りをするコンピュータはすごいですね!

{
latitude: 42.3605,
longitude: -71.0596,
timezone: "America/New_York",
currently: {
time: 1556073863,
summary: "Overcast",
icon: "cloudy",
nearestStormDistance: 0,
precipIntensity: 0,
precipProbability: 0,
temperature: 7.82,
apparentTemperature: 6.93,
dewPoint: 6.27,
humidity: 0.9,
pressure: 1011.35,
windSpeed: 1.72,
windGust: 2.83,
windBearing: 122,
cloudCover: 1,
uvIndex: 0,
visibility: 15.59,
ozone: 331.58
},
daily: {
summary: "Light rain today through Saturday, with high temperatures rising to 20°C on Sunday.",
icon: "rain",
data: [
{
time: 1555992000,
summary: "Overcast throughout the day.",
icon: "cloudy",
sunriseTime: 1556013117,
sunsetTime: 1556062523,
moonPhase: 0.65,
precipIntensity: 0.3277,
precipIntensityMax: 2.3292,
precipIntensityMaxTime: 1555995600,
precipProbability: 1,
precipType: "rain",
temperatureHigh: 12.1,
temperatureHighTime: 1556038800,
temperatureLow: 7.68,
temperatureLowTime: 1556071200,
apparentTemperatureHigh: 12.1,
apparentTemperatureHighTime: 1556038800,
apparentTemperatureLow: 6.71,
apparentTemperatureLowTime: 1556082000,
dewPoint: 7.77,
humidity: 0.88,
pressure: 1013.36,
windSpeed: 1.72,
windGust: 5.15,
windGustTime: 1556024400,
windBearing: 43,
cloudCover: 1,
uvIndex: 4,
uvIndexTime: 1556035200,
visibility: 11.04,
ozone: 332.64,
temperatureMin: 7.68,
temperatureMinTime: 1556071200,
temperatureMax: 12.1,
temperatureMaxTime: 1556038800,
apparentTemperatureMin: 6.86,
apparentTemperatureMinTime: 1556002800,
apparentTemperatureMax: 12.1,
apparentTemperatureMaxTime: 1556038800
}

終わりに

この記事では、講座の中で紹介されていたexpressを使用しない実装方法を紹介しました。この講座の中では、expressを使って同じapiを叩く実装も紹介されているので、後日紹介できればと思います。

ご指摘いただけることがありましたら、ご指摘いただけると幸いです。お読みいただきありがとうございました。