TypeScript 100天(第9天)

目录

网页

Intraday API

调用API

第9天的结论


本文构建了一个功能齐全的应用程序,用于检索Microsoft的日内交易价格并将其显示在表格中。

如果到目前为止您一直在跟随我们的旅程,那么我已经了解了TypeScript开发的构建块。在第8天,我谈到了使用TypeScript处理网页。最后,我承诺我将转向一个更复杂的应用程序,一个通过HTTP请求检索数据的应用程序,并使用它。在这篇文章中,我将介绍很多内容并构建一个功能齐全的应用程序,用于检索Microsoft的日内交易价格并将其显示在表格中。

为了让事情变得更有趣,我将介绍使用Bootstrap为应用程序设置样式,以使其在视觉上更有趣。以下屏幕截图显示了我们完成后应用程序的外观。

网页

我将把整个页面的HTML放在这里,而不是逐节构建。

<!DOCTYPE html>
<head>
    <title>100 Days of TypeScript - Day 9</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
     rel="stylesheet" 
     integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
     crossorigin="anonymous">
</head>
<body>
    <h1>Intraday Trading</h1>
    <h2 id="loading-state">Loading data for MSFT</h2>
    <table class="table table-striped">
        <thead class="table-dark">
            <tr>
                <th scope="col">Time</th>
                <th scope="col">Open</th>
                <th scope="col">High</th>
                <th scope="col">Low</th>
                <th scope="col">Close</th>
                <th scope="col">Volume</th>
            </tr>
        </thead>
        <tbody id="trading-table-body"></tbody>
    </table>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/
     bootstrap.bundle.min.js" 
     integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
     crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"
     data-main="scripts/api"></script>
</body>

页面的标题应该非常熟悉。这里的不同之处在于我已经链接到一个叫做内容交付网络(CDN)的东西来提供引导程序样式表。基本上,Bootstrap使用样式表和JavaScript来控制我们在屏幕上查看内容的方式。我们可以将CSSJavaScript文件本地存储在我们的项目中并从那里引用它们,或者我们可以使用这些文件的集中存储位置,即CDN

在页面的正文中,我添加了几个标题和一个表格。该h2元素被赋予一个id,因为我们将在页面加载数据后更新它。

在我们上桌之前,我们有几个正在加载的脚本。第一个脚本是与Bootstrap一起使用的JavaScript;同样,这是从CDN中提取的。第二个脚本对我们来说是新的。我已将底层功能分解为单独的TypeScript文件,这会影响它们如何加载到浏览器中。我正在使用requires.js为我管理这些文件的加载。该data-main部分告诉要求应首先加载哪个脚本。

当我分解后端代码时,我将向您展示我是如何组织TypeScript的,以便它创建一个适用于requires.js的模块。

再来看表格,我告诉Bootstrap,我希望将表格格式化为带有条纹交替行的表格。我通过添加class="table table-striped"来做到这一点。表格主体被赋予了一个id,因为我们将在我们的TypeScript中与它进行交互。

Intraday API

我将使用来自Alphavantage的交易信息。这允许人们获得一个免费的API密钥来与他们的各种共享API进行交互。我将使用的API日内交易。继续看看调用这个API的结果,它有助于给出一个看起来有点像这样的响应。

您可能会猜到我想将此API调用的结果映射到TypeScript,但JSON看起来有点有趣。我们想要映射的实际键看起来与我们过去通常看到的有很大不同,因此映射元数据,例如,意味着我们的键必须看起来不同。如果您已经开发了其他语言的应用程序,您可能会期望我们必须将键的名称映射到标准的TypeScript名称。在其他语言中,这通常如下所示:

[DataMember("1. open")]
public string Open { get; set; }

TypeScript不是这样工作的。相反,我们实际上可以使用键作为名称。这意味着我们可以像这样创建我们的MetaData类型:

export interface MetaData {
    '1. Information': string;
    '2. Symbol': string;
    '3. Last Refreshed': Date;
    '4. Output Size': string;
    '5. Time Zone': string;
};

不出所料,我们可以对时间序列做同样的事情。

export interface TimeSeries {
    '1. open': string;
    '2. high': string;
    '3. low': string;
    '4. close': string;
    '5. volume': string;
}

Alphavantage API 中,我们看到时间序列的键不是固定的,而是一个日期。问题是,我们如何对具有未知值的密钥进行建模?答案是使用称为索引签名TypeScript功能。索引签名的作用是告诉我们您将拥有一个未知结构的对象,但您知道键和值类型。如果我们知道我们有一个包含时间序列的string键,我们就使用语法进行建模。

[key: string]: TimeSeries

键的名字并不神奇。我们可以随意调用它,TypeScript并不关心。

考虑到这一点,我们的日内交易接口如下所示:

import { MetaData } from "./Metadata";
import { TimeSeries } from "./TimeSeries";

export interface Trading {
    'Meta Data': MetaData;
    'Time Series (5min)': { [key: string]: TimeSeries };
}

我们现在已经对Alphavantage API进行了建模。我很欣赏这些接口看起来有点奇怪,但是当我们从代码中调用API时,它们正是我们所需要的。如果您想知道为什么键是string而不是date,这是因为索引签名限制了它们可以使用的可接受类型,而Date不是这些类型之一。

旁注:我已将每个接口添加到自己的文件中,文件名称与接口名称匹配。

调用API

现在我们来到了有趣的部分,我已经到了我希望能够调用API的地步。要调用API,我将使用fetch命令。fetch给我们的是通过网络发出请求并获得响应的能力。关于这个命令,我们需要学习一些东西,所以让我们看看它在我们的代码库中的用法。(此代码出现在Intraday类中)。

public Get(symbol: string): Promise<Trading> {
    return fetch(this.apiSource + symbol).then(resp => {
        return resp.json();
    });
}

注意:在我分解此函数中发生的事情之前,为了使用该fetch函数,我们需要将DOM添加到tsconfig文件中的lib部分。我们之所以必须这样做,是因为这是作为浏览器操作可用的,所以需要利用DOM操作。

fetch操作是我们称之为异步的东西。这是一个花哨的术语,意味着在我们等待盘中交易调用的结果时,操作不会阻止我们做其他事情。这对我们来说意味着我们不会在我们的方法外直接返回Trading对象。相反,我们返回一个我们将在某个时候拥有一个Trading对象的PromisePromise是我们告诉代码我们将在未来某个时间点返回特定操作的方式。你会注意到我们在Get调用内部有一个返回操作。这是我们兑现promise的关键。

好的,所以我们知道Promise是什么,并且我们知道fetch调用是异步的。我们这里调用的内容就是我们要调用的端点,加上符号。当我展示这门课的全部内容时,我将在一分钟内回到这一点。在我这样做之前,我需要解决我们如何实现Promise。当fetch调用返回时,它会返回一个包含Response对象的Promise。我们使用该then方法将响应中的json返回到get调用。这对我们意味着,在成功的API调用(由HTTP 200响应状态指定)之后,我们将此响应从响应的json正文解码回我们的类型。

我们从哪里得到我们的API地址?好吧,我像这样在构造函数中填充它。

import { alphavantage } from "./Configuration/apiKey";
import { Trading } from "./Models/Trading";

export class Intraday {
    constructor(private apiSource = 'https://www.alphavantage.co/query?
    function=TIME_SERIES_INTRADAY&interval=5min&apikey=' + alphavantage() + 
    '&symbol=') { }

    public Get(symbol: string): Promise<Trading> {
        return fetch(this.apiSource + symbol).then(resp => {
            return resp.json();
        });
    }
}

在我们结束本节之前,我需要添加最后一个难题。在存储库中,您将看到Configuration中缺少apiKey条目。原因是我不想签入我的Alphavantage API密钥。您需要在代码的Configuration/apiKey.ts文件中添加以下函数(使用您自己的API密钥替换演示)。

export function alphavantage() {
    return 'demo';
}

9天的结论

我很感激在这篇文章中有很多东西需要掌握。在第10天,我将继续解构这个应用程序,并详细介绍在TypeScript中处理异步代码的其他方法。我还将展示如何通过调整TypeScript库来读取索引签名。

如果您想先睹为快,可以在Github上找到代码。

https://www.codeproject.com/Articles/5333551/100-Days-of-TypeScript-Day-9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值