Я создаю приложение погоды, чтобы попрактиковаться в использовании экспресс и ejs. Я использую app.get для запроса информации из API darkSky. Этот вызов выполняется один раз, и он успешен, я также могу отобразить его в своем файле index.ejs.
Я хотел бы добавить функцию часов реального времени с помощью moment.js, которая вызывается с помощью setInterval. (это закомментированная функция 'updateTime()')
Поскольку я не хочу вызывать API погоды каждый раз, когда обновляются часы, я думаю, что это должно быть вне вызова app.get.
Я не уверен, как это настроить, потому что кажется, что я не могу использовать манипуляции с DOM для добавления функции часов.
Есть ли способ получить динамический контент в моем ejs отдельно от моего вызова API?
(ps - фрагмент кода не будет работать, я просто хотел добавить код для точки отсчета)
const path = require('path')
const express = require('express')
const request = require('request')
const moment = require('moment')
const app = express();
const publicDirectoryPath = path.join(__dirname, '/public')
app.use(express.static(publicDirectoryPath))
app.set('view engine', 'ejs');
let sush = 'e20fe780791cad1d4d4d7b8484f970a5';
let lat = 39.892692;
let lng = -86.290568;
let apiUrl = `https://api.darksky.net/forecast/${sush}/${lat},${lng}`;
// function updateTime() {
// let dayTime = moment().format("dddd h:mma")
// console.info(dayTime)
// }
// setInterval(updateTime, 5000)
// app.use("/", function (req, res){
let dayTime;
function updateTime() {
dayTime = moment().format("dddd h:mma")
console.info(dayTime)
return dayTime
}
setInterval(updateTime, 5000)
// res.render('index.ejs', {dayTime:dayTime})
// })
app.get('/', function (req, res) {
request(apiUrl, function (error, response, body) {
if (error){
console.info('hey, hi, i didnt work - am i internet?')
}
weather_json = JSON.parse(body);
let dataDayThree = weather_json.daily.data[2].time;
let dataDayFour = weather_json.daily.data[3].time;
let dataDayFive = weather_json.daily.data[4].time
let daytwo = moment.unix(weather_json.daily.data[1].time).format("dddd")
let daythree = moment.unix(dataDayThree).format("dddd")
let dayfour = moment.unix(dataDayFour).format("dddd")
let dayfive = moment.unix(dataDayFive).format("dddd")
let iconCurrentlyOut = weather_json.currently.icon;
let iconTodayOut = weather_json.daily.data[0].icon;
let iconTomorrowOut = weather_json.daily.data[1].icon;
let iconDay3Out = weather_json.daily.data[2].icon;
let iconDay4Out = weather_json.daily.data[3].icon;
let iconDay5Out = weather_json.daily.data[4].icon;
function iconLooper(x){
switch (x) {
case 'rain':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--lV_oG1pX--/v1515194565/rainy-6_pzlrlc.svg";
break;
case 'snow':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--EsqjgOhi--/v1515194606/snowy-6_zl9kwx.svg";
break;
case 'clear-day':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s---6vDoixr--/v1515194528/day_shry4k.svg";
break;
case 'clear-night':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--CxSp0zXi--/v1515194530/night_quuh8p.svg";
break;
case 'sleet':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--yeTLFcMd--/v1515194570/rainy-7_sdbkyl.svg";
break;
case 'wind':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--ivgWegRI--/v1515194500/cloudy_vqbnvk.svg"
break;
case 'fog':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--ivgWegRI--/v1515194500/cloudy_vqbnvk.svg"
break;
case 'cloudy':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--ivgWegRI--/v1515194500/cloudy_vqbnvk.svg";
break;
case 'partly-cloudy-day':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--pkzBuC_i--/v1515194500/cloudy-day-1_n3vykl.svg";
break;
case 'snow':
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--DdrT7Iph--/v1515194500/cloudy-night-1_ro8fb5.svg";
break;
default:
console.info('i dont know whats goin on')
iconCurrently = "https://res.cloudinary.com/raphaeladdile/image/upload/s--ivgWegRI--/v1515194500/cloudy_vqbnvk.svg";
defaultTest = "i am an unkno"
}
return iconCurrently
}
///////////////////////////////////////////////////////////////////////////////////////////////
// if default in switch is activated add in what the actual weather is, like 'thunderstorms' //
//////////////////////////////////////////////////////////////////////////////////////////////
// function updateTime() {
// dayTime = moment().format("dddd h:mma")
// console.info(dayTime)
// return dayTime
// }
// setInterval(updateTime, 5000)
let weather = {
// date & time
//dayTime: updateTime(),
date: moment().format("MMM Do. YYYY"),
// current
currentTemp: Math.round(weather_json.currently.temperature),
summary: weather_json.currently.summary,
currentIcon: iconLooper(iconCurrentlyOut),
currentFeelLike: Math.round(weather_json.currently.apparentTemperature),
currentHumidity: Math.round(100 * (weather_json.currently.humidity)),
dailySummary: weather_json.daily.summary,
todayHi: Math.round(weather_json.daily.data[0].temperatureMax),
todayLo: Math.round(weather_json.daily.data[0].temperatureMin),
todayIcon: iconLooper(iconTodayOut),
// tomorrow
dayTwo: daytwo,
dayTwoHi: Math.round(weather_json.daily.data[1].temperatureMax),
dayTwoLo: Math.round(weather_json.daily.data[1].temperatureMin),
dayTwoIcon: iconLooper(iconTomorrowOut),
// day three
dayThree: daythree,
dayThreeHi: Math.round(weather_json.daily.data[2].temperatureMax),
dayThreeLo: Math.round(weather_json.daily.data[2].temperatureMin),
dayThreeIcon: iconLooper(iconDay3Out),
// day four
dayFour: dayfour,
dayFourHi: Math.round(weather_json.daily.data[3].temperatureMax),
dayFourLo: Math.round(weather_json.daily.data[3].temperatureMin),
dayFourIcon: iconLooper(iconDay4Out),
// day five
dayFive: dayfive,
dayFiveHi: Math.round(weather_json.daily.data[4].temperatureMax),
dayFiveLo: Math.round(weather_json.daily.data[4].temperatureMin),
dayFiveIcon: iconLooper(iconDay5Out)
}
let weatherData = {
weather: weather
}
res.render('index', weatherData)
})
});
app.listen(8000);<!DOCTYPE html>
<head>
<title>weatherApp</title>
<link rel = "stylesheet" href = "/css/style.css">
</head>
<body>
<div id = "container">
<!-- header
<div class = "header">
<button class = "refresh-btn" onClick = "window.location.reload()">Refresh</button>
</div>
-->
<div class = "row">
<!-- icon -->
<div class = "column iconColumn">
<img class = "currentWeatherIcon" src='<%=weather.currentIcon%>' />
</div>
<!-- descriptions -->
<div class = "column description">
<button class = "refresh-btn" onClick = "window.location.reload()">Refresh</button>
<h5><%=weather.currentTemp%>°F | <%=weather.summary%></h5>
<h5>Feels like <%=weather.currentFeelLike%>° F | humidity <%=weather.currentHumidity%>%</h5>
</div>
</div>
<h6 class = "daySummary"><%=weather.dailySummary%></h6>
<!-- table -->
<table>
<th>Today</th>
<th><%=weather.dayTwo%></th>
<th><%=weather.dayThree%></th>
<th><%=weather.dayFour%></th>
<th><%=weather.dayFive%></th>
<tr>
<td>
<img src='<%=weather.todayIcon%>' />
<div class = "hi-lo"><%=weather.todayHi%>°-<%=weather.todayLo%>°</div>
</td>
<td>
<img src='<%=weather.dayTwoIcon%>' />
<div class = "hi-lo"><%=weather.dayTwoHi%>°-<%=weather.dayThreeLo%>°</div>
</td>
<td>
<img src='<%=weather.dayThreeIcon%>' />
<div class = "hi-lo"><%=weather.dayThreeHi%>°-<%=weather.dayThreeLo%>°</div>
</td>
<td>
<img src='<%=weather.dayFourIcon%>' />
<div class = "hi-lo"><%=weather.dayFourHi%>°-<%=weather.dayFourLo%>°</div>
</td>
<td>
<img src='<%=weather.dayFiveIcon%>' />
<div class = "hi-lo"><%=weather.dayFiveHi%>°-<%=weather.dayFiveLo%>°</div>
</td>
</tr>
</table>
</div>
<script type = "text/javascript" src = "app.js"></script>
</body>
</html>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Чтобы выполнять манипуляции с DOM, вы должны включить JS-файл в HTML, как вы это делали с CSS. Измените свой <head> на это
<head>
<title>weatherApp</title>
<link rel = "stylesheet" href = "/css/style.css">
<script src = "/js/script.js">
</head>
Создайте каталог js рядом с css и файл script.js в нем, javascript, который вы туда добавите, может быть выполнен из вашего шаблона ejs.
Отображение простых часов с использованием клиентского javascript не имеет ничего общего с серверным рендерингом. Вы можете просто запустить код javascript внутри вашего файла ejs внутри тегов script. Проверьте этот простой пример, который вы можете найти на https://www.w3schools.com/js/:
<!DOCTYPE html>
<html>
<head>
</head>
<body onload = "startTime()">
<h3> Here is a simple clock.</h3>
<div id = "clock"></div>
<script>
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('clock').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
}
// add zero in front of numbers < 10
function checkTime(i) {
if (i < 10) {i = "0" + i};
return i;
}
</script>
</body>
</html>Рад помочь вам. Как правило, лучше поместить логику и функции javascript в отдельный файл. Если ответ решает вашу проблему, не стесняйтесь пометить ответ как принятый.
Это фантастично! Спасибо вам большое за ваш ответ! Было бы лучше поместить это в собственный файл javascript, или это нормально?