Изготовление сайтов в Мариуполе, ДНР. Создание приложения погоды из командной строки в Deno

Если вы следили за нашими вводными статьями о Deno, вы, вероятно, заинтересованы в том, чтобы попробовать написать свою первую программу. В этой статье мы рассмотрим установку среды выполнения Deno и создание программы погоды из командной строки, которая будет принимать название города в качестве аргумента и возвращать прогноз погоды на следующие 24 часа.

Для написания кода для Deno я настоятельно рекомендую Visual Studio Code с официальным плагином Deno. Чтобы было немного интереснее, мы напишем приложение на TypeScript.

Установка Дено

Во-первых, давайте установим Deno локально, чтобы мы могли начать писать наш скрипт. Процесс прост, так как есть сценарии установки для всех трех основных операционных систем.

Окна

В Windows вы можете установить Deno из PowerShell:

iwr https://deno.land/x/install/install.ps1 -useb | iex

линукс

В терминале Linux вы можете использовать следующую команду:

curl -fsSL https://deno.land/x/install/install.sh | sh

macOS

На Mac Deno можно установить с помощью Brew:

brew install deno

После установки

После завершения процесса установки вы можете проверить правильность установки Deno, выполнив следующую команду:

deno —version

Теперь вы должны увидеть что-то похожее на это:

deno 1.2.0

v8 8.5.216

typescript 3.9.2

Давайте создадим папку для нашего нового проекта (внутри вашей домашней папки или там, где вы хотите хранить свои проекты кодирования) и добавим index.tsфайл:

mkdir weather-app

cd weather-app

code index.ts

Примечание. Как я уже упоминал выше, для этого урока я использую VS Code. Если вы используете другой редактор, замените последнюю строку выше.

Получение пользовательского ввода

Наша программа будет получать прогноз погоды для заданного города, поэтому нам нужно будет принять название города в качестве аргумента при запуске программы. Аргументы, предоставляемые скрипту Deno, доступны в виде файлов Deno.args. Давайте выведем эту переменную в консоль, чтобы посмотреть, как она работает:

console.log (Deno.args) ;

Теперь запустите скрипт с помощью следующей команды:

deno run index.ts —city London

Вы должны увидеть следующий вывод:

[ «—city», «London» ]

Хотя мы могли бы сами разобрать этот массив аргументов, стандартная библиотека Deno включает модуль под названием flags, который позаботится об этом за нас. Чтобы использовать его, все, что нам нужно сделать, это добавить оператор импорта в начало нашего файла:

import { parse } from «https: //deno.land/std@0.61.0/flags/mod.ts»;

Примечание: примеры в документации для модулей стандартной библиотеки дадут вам неверсионный URL-адрес (например, https://deno.land/std/flags/mod.ts), который всегда будет указывать на последнюю версию кода. Хорошей практикой является указание версии в вашем импорте, чтобы гарантировать, что ваша программа не будет нарушена будущими обновлениями. *

Давайте используем импортированную функцию, чтобы преобразовать массив аргументов во что-то более полезное:

const args = parse (Deno.args) ;

Мы также изменим сценарий, чтобы вывести нашу новую argsпеременную из системы, чтобы увидеть, как она выглядит. Итак, теперь ваш код должен выглядеть так:

import { parse } from «https: //deno.land/std@0.61.0/flags/mod.ts»;

const args = parse (Deno.args) ;

console.log (args) ;

Теперь, если вы запустите скрипт с тем же аргументом, что и раньше, вы должны увидеть следующий вывод:

Download https://deno.land/std@0.61.0/flags/mod.ts

Download https://deno.land/std@0.61.0/_util/assert.ts

Check file: ///home/njacques/code/weather-app/index.ts

{ _: [], city: «London» }

Всякий раз, когда Deno запускает сценарий, он проверяет наличие новых операторов импорта. Любые удаленно размещенные импорты загружаются, компилируются и кэшируются для будущего использования. Функция parseпредоставила нам объект, у которого есть cityсвойство, содержащее наш ввод.

Примечание: если вам по какой-либо причине нужно повторно загрузить импорт для скрипта, вы можете запустить deno cache —reload index.ts.

Мы также должны добавить проверку cityаргумента и выйти из программы с сообщением об ошибке, если он не указан:

if (args.city === undefined) {

console.error («No city supplied») ;

Deno.exit () ;

}

Разговор с API погоды

Мы собираемся получать данные прогноза из OpenWeatherMap. Вам нужно будет зарегистрировать бесплатную учетную запись, чтобы получить ключ API. Мы будем использовать их API прогноза на 5 дней, передав ему название города в качестве параметра.

Давайте добавим код для получения прогноза и выведем его в консоль, чтобы посмотреть, что мы получим:

import { parse } from «https: //deno.land/std@0.61.0/flags/mod.ts»;

const args = parse (Deno.args) ;

if (args.city === undefined) {

console.error («No city supplied») ;

Deno.exit () ;

}

const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’;

const res = await fetch (`https: //api.openweathermap.org/data/2.5/forecast? q=${args.city}&units=metric&appid=${apiKey}`) ;

const data = await res.json () ;

console.log (data) ;

Deno пытается поддерживать множество браузерных API, где это возможно, поэтому здесь мы можем использовать fetchбез необходимости импортировать какие-либо внешние зависимости. Мы также используем поддержку верхнего уровня await: обычно нам приходится оборачивать любой код, который использует awaitфункцию async, но TypeScript не заставляет нас делать это, что делает код немного лучше.

Если вы попытаетесь запустить этот скрипт сейчас, вы увидите сообщение об ошибке:

Check file: ///home/njacques/code/weather-app/index.ts

error: Uncaught PermissionDenied: network access to «https: //api.openweathermap.org/data/2.5/forecast? q=London&units=metric&appid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx», run again with the —allow-net flag

at unwrapResponse ($deno$/ops/dispatch_json.ts:42:11)

at Object.sendAsync ($deno$/ops/dispatch_json.ts:93:10)

at async fetch ($deno$/web/fetch.ts:266:27)

at async index.ts:12:13

По умолчанию все сценарии Deno запускаются в защищенной песочнице: у них нет доступа к сети, файловой системе или таким вещам, как переменные среды. Сценарям должны быть явно предоставлены права доступа к системным ресурсам, к которым им необходим доступ. В этом случае сообщение об ошибке помогает нам узнать, какое разрешение нам нужно и как его включить.

Давайте снова вызовем скрипт с правильным флагом:

deno run —allow-net index.ts —city London

На этот раз мы должны получить ответ JSON от API:

{

cod: «200»,

message: 0,

cnt: 40,

list: [

{

dt: 1595527200,

main: {

temp: 22.6,

feels_like: 18.7,

temp_min: 21.04,

temp_max: 22.6,

pressure: 1013,

sea_level: 1013,

grnd_level: 1011,

humidity: 39,

temp_kf: 1.56

},

weather: [ [Object] ],

clouds: { all: 88 },

wind: { speed: 4.88, deg: 254 },

visibility: 10000,

pop: 0,

sys: { pod: «d» },

dt_txt: «2020-07-23 18:00:00»

},

...

],

city: {

id: 2643743,

name: «London»,

coord: { lat: 51.5085, lon: -0.1257 },

country: «GB»,

population: 1000000,

timezone: 3600,

sunrise: 1595477494,

sunset: 1595534525

}

}

Вы можете просмотреть полную информацию о том, что возвращается в ответе, но в основном нас интересует массив данных прогноза в формате list. Каждый объект в массиве содержит метку времени (dt), mainобъект с подробной информацией об атмосферных условиях (температура, влажность, давление и т. д.) и weatherмассив, содержащий объект с описанием прогнозируемой погоды.

Мы собираемся mainперебрать массив, чтобы получить прогноз времени, температуры и погодных условий. Начнем с ограничения количества записей, чтобы они охватывали только 24-часовой период. Данные прогноза, доступные нам на бесплатном плане, доступны только с трехчасовыми интервалами, поэтому нам нужно получить восемь записей:

const forecast = data.list.slice (0, 8)

Мы сопоставим каждый из элементов прогноза и вернем массив интересующих нас данных:

const forecast = data.list.slice (0, 8).map (item => [

item.dt,

item.main.temp,

item.weather[0].description,

]) ;

Если мы попытаемся запустить скрипт сейчас, мы получим ошибку компиляции (если вы используете IDE, такую ​​как VS Code, вы также получите эту ошибку, отображаемую при вводе кода): Параметр «item» неявно имеет 'любой тип.

TypeScript требует, чтобы мы сообщали ему о типе переменной item, чтобы знать, делаем ли мы с ней что-либо, что может вызвать ошибку во время выполнения. Давайте добавим интерфейс, чтобы описать структуру item:

interface forecastItem {

dt: string;

main: { temp: number; };

weather: { description: string; }[];

}

Обратите внимание, что мы описываем здесь не все свойства объекта, а только те, к которым мы действительно собираемся обращаться. В нашей ситуации мы знаем, какие свойства нам нужны.

Давайте добавим наш новый тип в наш mapобратный вызов:

const forecast = data.list.slice (0, 8).map ((item: forecastItem) => [

item.dt,

item.main.temp,

item.weather[0].description,

]) ;

Если вы используете IDE с поддержкой TypeScript, она должна иметь возможность автозаполнения свойств по itemмере ввода благодаря типу интерфейса, который мы предоставили.

Создайте класс обслуживания

Создайте интерфейс для вывода

Форматирование вывода

Теперь, когда у нас есть набор данных, которые мы хотим, давайте посмотрим, как красиво отформатировать их для отображения пользователю.

Во-первых, давайте преобразуем значение метки времени в удобочитаемую дату. Если мы посмотрим на список сторонних модулей Deno и введем в поиск «date», то увидим в списке date-fns. Мы можем использовать ссылку отсюда, чтобы импортировать функции, которые мы собираемся использовать, в наше приложение Deno:

import { fromUnixTime, format } from «https: //deno.land/x/date_fns@v2.15.0/index.js»;

Теперь мы можем передать метку времени через fromUnixTimeфункцию, чтобы получить объект Date, а затем передать этот объект format, чтобы получить строку даты, которую мы хотим:

format (fromUnixTime (item.dt), «do LLL, k: mm», {})

Строка форматирования do LLL, k: mmдаст нам дату в следующем формате: «24 июля, 13:00».

Примечание: мы передаем пустой объект в качестве третьего аргумента formatисключительно для того, чтобы отключить предупреждение IDE об ожидаемом количестве аргументов. Код по-прежнему будет работать без него.

Пока мы это делаем, давайте округлим значение температуры до одного десятичного знака и добавим индикатор единиц измерения:

`${item.main.temp.toFixed (1) }C`

Теперь, когда данные нашего прогноза отформатированы и готовы к отображению, давайте представим их пользователю в виде аккуратной маленькой таблицы с помощью модуля ascii_table:

import AsciiTable from 'https: //deno.land/x/ascii_table/mod.ts’;

...

const table = AsciiTable.fromJSON ({

title: `${data.city.name} Forecast`,

heading: [ 'Time’, 'Temp’, 'Weather’],

rows: forecast

})

console.log (table.toString ())

Сохраните и запустите скрипт, и теперь мы должны красиво отформатировать и представить прогноз для выбранного нами города на следующие 24 часа:

. --------------------------------------------.

| London Forecast |

|--------------------------------------------|

| Time | Temp | Weather |

|-----------------|-------|------------------|

| 23rd Jul, 19:00 | 17.8C | light rain |

| 23rd Jul, 22:00 | 16.8C | light rain |

| 24th Jul, 1:00 | 16.0C | broken clouds |

| 24th Jul, 4:00 | 15.6C | light rain |

| 24th Jul, 7:00 | 16.0C | broken clouds |

| 24th Jul, 10:00 | 18.3C | scattered clouds |

| 24th Jul, 13:00 | 20.2C | light rain |

| 24th Jul, 16:00 | 20.2C | light rain |

'--------------------------------------------'

Полный список кодов

Это довольно компактный скрипт, но вот полный листинг кода:

import { parse } from «https: //deno.land/std@0.61.0/flags/mod.ts»;

import {

fromUnixTime,

format,

} from «https: //deno.land/x/date_fns@v2.15.0/index.js»;

import AsciiTable from «https: //deno.land/x/ascii_table/mod.ts»;

const args = parse (Deno.args) ;

if (args.city === undefined) {

console.error («No city supplied») ;

Deno.exit () ;

}

const apiKey = «xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx»;

const res = await fetch (

`https: //api.openweathermap.org/data/2.5/forecast? q=${args.city}&units=metric&appid=${apiKey}`,

) ;

const data = await res.json () ;

interface forecastItem {

dt: string;

main: { temp: number };

weather: { description: string }[];

}

const forecast = data.list.slice (0, 8).map ((item: forecastItem) => [

format (fromUnixTime (item.dt), «do LLL, k: mm», {}),

`${item.main.temp.toFixed (1) }C`,

item.weather[0].description,

]) ;

const table = AsciiTable.fromJSON ({

title: `${data.city.name} Forecast`,

heading: [«Time», «Temp», «Weather»],

rows: forecast,

}) ;

console.log (table.toString ());

Резюме

Теперь у вас есть собственная работающая программа командной строки Deno, которая даст вам прогноз погоды на следующие 24 часа. Следуя этому руководству, вы теперь должны быть знакомы с тем, как запускать новую программу, импортировать зависимости из стандартной библиотеки и сторонних поставщиков и предоставлять разрешения сценариям.

Итак, войдя во вкус к написанию программ для Deno, что делать дальше? Я определенно рекомендую прочитать руководство, чтобы узнать больше о различных параметрах командной строки и встроенных API, но также следите за SitePoint, чтобы получить больше контента Deno!

Делитесь нашими материалами с друзьями!

 

 

Заказать разработку сайта