اگر مقالات مقدماتی ما در مورد Deno را دنبال کرده اید ، احتمالاً علاقه مند هستید که در نوشتن اولین برنامه خود تلاش کنید. در این مقاله ، ما می خواهیم با نصب زمان اجرا Deno ، و ایجاد یک برنامه خط فرمان آب و هوا که نام یک شهر را به عنوان استدلال در نظر می گیرد و پیش بینی آب و هوا را برای 24 ساعت آینده باز می گردیم.

برای نوشتن کد برای Deno ، من بسیار توصیه می کنم Visual Studio Code با مقام پلاگین Deno. برای اینکه همه چیز کمی جالب تر شود ، قصد داریم برنامه را با TypeScript بنویسیم.

در حال نصب Deno

در ابتدا ، بیایید Deno را به صورت محلی نصب کنیم تا بتوانیم نوشتن اسکریپت خود را شروع کنیم. این فرایند ساده است ، زیرا اسکریپت های نصب کننده برای هر سه سیستم عامل اصلی وجود دارد.

پنجره ها

در ویندوز ، می توانید Deno را از PowerShell نصب کنید:

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

لینوکس

از ترمینال Linux می توانید از دستور زیر استفاده کنید:

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

سیستم عامل مکینتاش

در 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 شامل ماژولی به نام پرچم ها که از این امر برای ما مراقبت خواهد کرد. برای استفاده از آن ، تنها کاری که باید انجام دهیم این است که بیانیه واردات را به بالای پرونده خود اضافه کنیم:

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 تابع یک شی object را در اختیار ما قرار داده است که دارای یک city ویژگی حاوی ورودی ما.

توجه: اگر به هر دلیلی نیاز به بارگیری مجدد واردات برای یک اسکریپت دارید ، می توانید اجرا کنید deno cache --reload index.ts.

ما همچنین باید یک چک برای اضافه کنیم city در صورت عدم ارائه برنامه ، با یک پیام خطا برنامه را ترک کنید:

if (args.city === undefined) {
    console.error("No city supplied");
    Deno.exit();
}

صحبت با API Weather

ما می خواهیم داده های پیش بینی خود را از این طریق دریافت کنیم OpenWeatherMap. برای بدست آوردن کلید API باید برای یک حساب رایگان ثبت نام کنید. ما از آنها استفاده خواهیم کرد 5 روز پیش بینی API، عبور از آن یک نام شهر به عنوان یک پارامتر.

بیایید چند کد برای واکشی پیش بینی اضافه کنیم و آن را در کنسول وارد کنیم ، تا ببینیم چه چیزی بدست می آوریم:

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 در یک sandbox امن اجرا می شوند: آنها به شبکه ، سیستم فایل یا مواردی مانند متغیرهای محیط دسترسی ندارند. اسکریپت ها باید صریحاً مجوز منابع سیستمی را که برای دسترسی به آنها لازم هستند ، بگیرند. در این حالت ، پیام خطا به ما کمک می کند تا بدانیم به کدام مجوز نیاز داریم و چگونه آن را فعال کنیم.

بیایید دوباره اسکریپت را با پرچم صحیح فراخوانی کنیم:

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 جسمی با جزئیات شرایط جوی (دما ، رطوبت ، فشار و غیره) ، و a 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 استفاده می کنید ، با تایپ کد نیز این خطا نمایش داده می شود): پارامتر “مورد” به طور ضمنی از نوع “هر” برخوردار است.

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-fns در لیست برای وارد کردن توابعی که قصد استفاده از آن را در برنامه Deno خود داریم ، می توانیم از این پیوند استفاده کنیم:

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

اکنون می توانیم مهر زمان را از طریق عبور دهیم fromUnixTime تابع ، برای بدست آوردن یک شی تاریخ ، و سپس انتقال این شی به 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 داخلی ، اما همچنین برای محتوای Deno بیشتر به SitePoint توجه داشته باشید!

بنیادهای Deno

با Deno سرعت بگیرید. مجموعه بنیادهای Deno ما به شما کمک می کند اولین قدم های خود را به دنیای Deno و فراتر از آن بردارید ، و ما دائماً به آن اضافه می کنیم. ما آموزش های لازم برای حرفه ای شدن را برای شما به ارمغان می آوریم. همیشه می توانید شاخص ما را در پایان مقدمه Deno به روز کنید:

➤ بنیادهای Deno