首发于公众号《前端全栈开发者》,第一时间阅读最新文章,会优先两天发表新文章。关注后私信回复:大礼包,送某网精品视频课程网盘资料,准能为你节省不少钱!
在本文中,我们将通过安装Deno运行时,并创建一个命令行天气程序,该程序将把一个城市名称作为参数,并返回未来24小时的天气预报。
要为Deno编写代码,我强烈建议将Visual Studio Code与官方的Deno插件一起使用。为了使事情更有趣,我们将使用TypeScript编写应用程序。
安装Deno
首先,让我们把Deno安装到本地,这样我们就可以开始编写脚本了。这个过程很简单,因为三大操作系统都有安装脚本。
Windows
在Windows上,你可以从PowerShell安装Deno:
iwr https://deno.land/x/install/install.ps1 -useb | iex
Linux
在Linux终端上,可以使用以下命令:
curl -fsSL https://deno.land/x/install/install.sh | sh
macOS
在Mac上,可以将Brew与Deno一起安装:
brew install deno
安装后
安装过程完成后,你可以通过运行以下命令检查Deno是否正确安装。
deno --version
你现在应该看到类似以下内容:
deno 1.2.0
v8 8.5.216
typescript 3.9.2
让我们为我们的新项目创建一个文件夹(在你的home文件夹内,或者任何你喜欢保存代码项目的地方)并添加一个 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 杭州
你应该看到以下输出:
[ "--city", "杭州" ]
尽管我们可以自己解析此参数数组,但Deno的标准库包括一个名为flags的模块,它将为我们解决这一问题。要使用它,我们要做的就是在文件顶部添加一个 import
语句:
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
注意:标准库模块的文档中的例子会给你一个未版本化的URL(如 https://deno.land/std/flags/m...,它将始终指向最新版本的代码。在你的导入中指定一个版本是一个很好的做法,以确保你的程序不会被未来的更新所破坏。
让我们使用导入的函数将参数数组解析为更有用的内容:
const args = parse(Deno.args);
我们还将修改脚本来打印新的 args
变量,看看是什么样子的。所以现在你的代码应该是这样的:
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
const args = parse(Deno.args);
console.log(args);
现在,如果使用与以前相同的参数运行脚本,则应该看到以下输出:
Download https://deno.land/[email protected]/flags/mod.ts
Download https://deno.land/[email protected]/_util/assert.ts
Check file:///home/njacques/code/weather-app/index.ts
{ _: [], city: "杭州" }
每当Deno运行脚本时,它都会检查新的import语句。任何远程托管的导入都将被下载,编译和缓存以备将来使用。parse
函数为我们提供了一个对象,该对象具有包含我们输入内容的 city
属性。
注意:如果你因为任何原因需要为一个脚本重新下载导入,你可以运行deno cache --reload index.ts。
我们还应该增加对 city
参数的检查,如果没有提供城市参数,则以错误信息退出程序。
if (args.city === undefined) {
console.error("No city supplied");
Deno.exit();
}
使用天气API
我们将从 tianqiapi.com 获取预报数据。你需要注册一个免费账户,以获得一个API密钥。我们将使用他们的专业七日天气接口,传递一个城市名称作为参数。
让我们添加一些代码以获取天气预报并将其打印到控制台,以查看得到的结果:
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
const args = parse(Deno.args);
if (args.city === undefined) {
console.error("No city supplied");
Deno.exit();
}
const appid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const appsecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const res = await fetch(`https://yiketianqi.com/api?version=v9&appid=${appid}&appsecret=${appsecret}`);
const data = await res.json();
console.log(data);
Deno尝试在可能的情况下支持许多浏览器API,因此在这里我们可以使用 fetch
而不必导入任何外部依赖项。我们还利用了对await的支持:通常,我们必须将所有使用 await
的代码包装在 async
函数中,但是TypeScript并没有使我们这样做,这使得代码变得更好了。
如果你现在尝试运行此脚本,则会遇到错误消息:
Compile file:///Users/zhangbing/github/CodeTest/Deno/weather-app/index.ts
error: Uncaught PermissionDenied: network access to "https://yiketianqi.com/api?version=v9&appid=xxxxxxxx&appsecret=xxxxxxx", run again with the --allow-net flag
at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
at Object.sendAsync ($deno$/ops/dispatch_json.ts:98:10)
at async fetch ($deno$/web/fetch.ts:296:27)
at async file:///Users/zhangbing/github/CodeTest/Deno/weather-app/index.ts:13:13
默认情况下,所有Deno脚本都在安全的沙箱中运行:它们无权访问网络,文件系统或诸如环境变量之类的东西。需要为脚本明确授予对其需要访问的系统资源的权限。在这种情况下,错误消息将帮助我们了解所需的权限以及如何启用它。
让我们再次调用脚本,并带有正确的标志:
deno run --allow-net index.ts --city 杭州
这次,我们应该从API取回JSON响应:
{
cityid: "101210101",
city: "杭州",
cityEn: "hangzhou",
country: "中国",
countryEn: "China",
update_time: "2020-08-13 16:51:27",
data: [
{
day: "13日(星期四)",
date: "2020-08-13",
week: "星期四",
wea: "多云",
wea_img: "yun",
wea_day: "多云",
wea_day_img: "yun",
wea_night: "多云",
wea_night_img: "yun",
tem: "37",
tem1: "38",
tem2: "28",
humidity: "40%",
visibility: "暂缺",
pressure: "1002",
win: [ "西南风", "无持续风向" ],
win_speed: "4-5级转<3级",
win_meter: "小于12km/h",
sunrise: "05:24",
sunset: "18:43",
air: "35",
air_level: "优",
air_tips: "空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!",
alarm: {
alarm_type: "高温",
alarm_level: "橙色",
alarm_content: "杭州市气象台2020年8月13日9时05分发布高温橙色预警信号:受副热带高压控制,预计今天主城区和钱塘新区最高气温将达38℃左右,请注意做好防暑降温等工作。(预警信息来源:国家预警信息发布中心)"
},
hours: [
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object]
],
index: [ [Object], [Object], [Object], [Object], [Object], [Object] ]
},
... ...
]
}
返回字段的含义可以查看API文档。data
数组就是每日数据列表,1-7日,共7组。每个对象中包含气象预警(alarm
)、小时预报(hours
)、生活指数(index
)、空气质量指数(aqi
) 数据。
为了简单起见,我们只获取几个简单的数据:日期、天气、实时温度空和空气质量等级四个数据,为此需要遍历数组:
const forecast = data.data.map((item) => [
item.day, // 日期
item.wea, // 天气
item.tem, // 实时温度
item.air_level, // 空气质量等级
]);
如果我们现在尝试运行脚本,我们会得到一个编译错误(如果你使用像VS代码这样的IDE,在键入代码时也会得到这个错误):参数 ' item’ 隐式地具有一个 ‘any' 类型。
TypeScript要求我们告诉它该 item
是什么类型的变量,以便知道我们是否对它做了任何可能在运行时导致错误的事情。让我们添加一个接口,以描述 item
的结构:
interface forecastItem {
day: string;
wea: string;
tem: string;
air_level: string;
}
让我们将新类型添加到map回调中:
const forecast = data.data.map((item: forecastItem) => [
item.day, // 日期
item.wea, // 天气
item.tem, // 实时温度
item.air_level, // 空气质量等级
]);
如果你使用的IDE支持TypeScript,它应该能够在你输入时自动完成 item
的类型,这要感谢我们提供的接口类型。
现在运行结果输入如下:
forecast [
[ "13日(星期四)", "多云转晴", "36", "优" ],
[ "14日(星期五)", "晴", "37", "" ],
[ "15日(星期六)", "晴", "37", "" ],
[ "16日(星期日)", "多云转晴", "37", "" ],
[ "17日(星期一)", "晴", "37", "" ],
[ "18日(星期二)", "晴", "37", "" ],
[ "19日(星期三)", "晴", "38", "" ]
]
格式化输出
现在我们有了所需的数据集,接下来让我们来看一下如何格式化它以便显示给用户。让我们使用 ascii_table 模块将其显示在整洁的小表中:
import AsciiTable from 'https://deno.land/x/ascii_table/mod.ts';
...
const table = AsciiTable.fromJSON({
title: `${args.city}七日天气预报`,
heading: [ '日期', '天气', '实时温度', '风', '空气质量', '天气预警'],
rows: forecast
})
console.log(table.toString())
保存并运行脚本,现在我们应该已经对接下来的7日内的所选城市进行了格式化并给出了预报:
完整代码清单
这是一个紧凑的脚本,但是下面是完整的代码清单,也可去我们的 Github。
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
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();
}
// 你自己的API密钥
const appid = "xxxxxxxx";
const apiKey = "xxxxxxxxx";
const res = await fetch(
`https://yiketianqi.com/api?version=v9&appid=${appid}&appsecret=${apiKey}`,
);
const data = await res.json();
interface forecastItem {
day: string;
wea: string;
tem: string;
air_level: string;
}
const forecast = data.data.map((item: forecastItem) => [
item.day, // 日期
item.wea, // 天气
item.tem, // 实时温度
item.air_level, // 空气质量等级
]);
const table = AsciiTable.fromJSON({
title: `${args.city}七日天气预报`,
heading: ["日期", "天气", "温度", "空气质量"],
rows: forecast,
});
console.log(table.toString());
总结
现在,你有了自己的正在运行的Deno命令行程序,该程序将为你提供接下来7日天气预报。通过遵循本教程,你现在应该熟悉如何启动新程序,从标准库和第三方导入依赖项以及授予脚本权限。
那么,在尝到了为Deno编写程序的甜头之后,接下来你应该去哪里呢?你觉得Deno如何?
推荐阅读
- EmailJS:5步使用JavaScript直接从前端发送电子邮件
- 如何使用JavaScript访问设备前后摄像头
- 使用Typescript和ES模块发布Node模块
- Javascript开发人员偏爱Deno而不是Node的5大原因
- 如何使用CSS Paint API动态创建与分辨率无关的可变背景
- 这9种Vue技术你掌握了吗?不信你全知道
- 2020年的12个Vue.js开发技巧和窍门
- 在Vue.js编写更好的v-for循环的6种技巧
- 实战:使用React Hook一步一步创建一个可排序表格组件
- 实战 | HTML页面生成器:使用JavaScript和Node创建CLI
- 实战 | 从零开始使用JavaScript制作自己的命令行(CLI工具)
- 【实战】这个炫酷的播放粒子效果,你也可以学会!使用Web动画API制作