十一、答案

第一章

  1. 使用联合类型,可以编写一个接受FahrenheitToCelsius类或CelsiusToFahrenheit类的方法:
class Converter {
    Convert(temperature : number, converter : FahrenheitToCelsius | CelsiusToFahrenheit) : number {
        return converter.Convert(temperature);
    }
}

let converter = new Converter();
console.log(converter.Convert(32, new CelsiusToFahrenheit()));
  1. 要接受键/值对,我们需要使用映射。 将我们的记录添加到它看起来像这样:
class Commands {
    private commands = new Map<string, Command>();
    public Add(...commands : Command[]) {
        commands.forEach(command => {
            this.Add(command);
        })
    }
    public Add(command : Command) {
        this.commands.set(command.Name, command);
    }
}

let command = new Commands();
command.Add(new Command("Command1", new Function()), new Command("Command2", new Function()));

这里我们添加了两个方法。 如果我们想一次性添加多个命令,可以使用 REST 参数来接受命令数组。

  1. 当我们的Add方法被调用时,我们可以使用一个装饰器来自动记录日志。 例如,我们的log方法看起来像这样:
function Log(target : any, propertyKey : string | symbol, descriptor : PropertyDescriptor) {
    let originalMethod = descriptor.value;
    descriptor.value = function() {
        console.log(`Added a command`);
        originalMethod.apply(this, arguments);
    }
    return descriptor;
}

我们只会把这个添加到下面的Add方法中,因为接受 REST 参数的Add方法会调用这个方法:

@Log
public Add(command : Command) {
    this.commands.set(command.Name, command);
}

不要忘记我们使用@符号来表示这是一个装饰器。

  1. 要添加具有相等大小的六个中等列的行,我们使用六个div语句,并将类设置为col-md-2,如下所示:
<div class="row">
  <div class="col-md-2">
  </div>
  <div class="col-md-2">
  </div>
  <div class="col-md-2">
  </div>
  <div class="col-md-2">
  </div>
  <div class="col-md-2">
  </div>
  <div class="col-md-2">
  </div>
</div>

请记住,在 Bootstrap 的讨论中,一行中的列数应该等于 12。

第三章

  1. React 为我们提供了特殊的文件类型,.jsx(用于 JavaScript)或.tsx(用于 TypeScript),用来创建一个可以转译为 JavaScript 的文件,所以 React 接受看起来像 HTML 的元素,并将它们呈现为 JavaScript。
  2. classfor在 JavaScript 中都是保留关键字。 由于.tsx文件似乎在同一个方法中混合了 JavaScript 和 HTML,我们需要别名来指定 CSS 类和label关联的控件。 React 提供className来指定应用于 HTML 元素的类,并提供htmlFor来指定标签与什么控件相关联。
  3. 当我们创建验证器时,我们是在创建可重用的代码片段,这些代码片段可以用于实际执行特定类型的验证; 例如,检查以确保字符串是最小长度。 因为这些设计是可重用的,所以我们必须将它们与验证代码分开,而验证代码是我们实际应用验证的地方。
  4. [0-9]替换为\d,将^(?:\\((?:[0-9]{3})\\)|(?:[0-9]{3}))[-. ]?(?:[0-9]{3})[-. ]?(?:[0-9]{4})$转换为^(?:\\((?:\d{3})\\)|(?:\d{3}))[-. ]?(?:\d{3})[-. ]?(?:\d{4})$
  5. 通过硬删除,我们从数据库中删除物理记录。 使用软删除,我们保留记录,但对它应用一个标记,这意味着记录不再活动。

第四章

  1. MEAN 堆栈由四个主要部分组成:
    • MongoDB:MongoDB 是一个 NoSQL 数据库,它成为了事实上的标准,在客户机/服务器应用中使用 Node 构建数据库支持。 还有其他可用的数据库选项,但 MongoDB 是一个非常流行的选择。
    • Express:Express 总结了在 Node 下使用服务器端代码的复杂性,使其更易于使用。 例如,如果我们想处理 HTTP 请求,与编写等效的 Node 代码不同,Express 使这一点变得很简单。
    • Angular:Angular 是一个客户端框架,它让创建强大的 web 前端变得更容易。
    • Node:Node(或 Node.js)是我们应用在服务器上的运行时环境。
  2. 我们提供一个前缀以使组件独一无二。 假设我们有一个组件,我们想调用label; 显然,这将与内置的 HTML 标签冲突。 为了避免这种冲突,我们的组件选择器将是atp-label。 由于 HTML 控件从不使用连字符,我们保证不会与现有的控件选择器发生冲突
  3. 要启动我们的 Angular 应用,我们在 Angular 顶层文件夹中运行以下命令:
ng serve --open
  1. 就像我们自己的语言被分解成单词和标点符号一样,我们也可以将视觉元素分解成颜色和深度等结构。 例如,语言告诉我们颜色的含义,所以如果我们在应用的一个屏幕上看到一个带有一种颜色的按钮,那么它应该在应用的其他屏幕上具有相同的潜在用法; 我们不会用一个绿色按钮在一个对话框上表示 OK,然后在另一个对话框上表示 Cancel。 设计语言背后的理念是元素应该是一致的。 因此,如果我们将应用创建为 Material 应用,那么使用 Gmail(例如)的人应该熟悉它。
  2. 我们使用以下命令创建服务:
ng generate service <<servicename>>

可以缩写为:

ng g s <<servicename>>
  1. 每当一个请求进入我们的服务器时,我们需要确定如何最好地处理请求,这意味着我们必须将它路由到适当的功能块来处理请求。 快速路由是我们用来完成这一任务的机制。
  2. RxJS 实现了观察者模式。 这种模式有一个对象(称为主题),跟踪一个数组的依赖关系(称为观察家),通知他们的有趣的行为,如状态改变。

  3. CORS代表Cross-Origin Request Sharing。 通过 CORS,我们让已知外部地点可以进入我们站点的受限操作。 在我们的代码中,由于 Angular 是从一个不同的站点运行到我们的 web 服务器的(localhost:4200,而不是localhost:3000),我们需要启用 CORS 支持 post,否则当我们从 Angular 发出请求时,我们不会返回任何东西。

第五章

  1. GraphQL 并不打算完全替代 REST 客户机。 它可以作为一种协作技术,因此它本身可以很好地使用多个 REST api 来生成图。
  2. 突变是一种以某种方式改变图中的数据的操作。 我们可能想要向图中添加新项、更新项或删除项。 重要的是要记住,更改只是更改图——如果更改必须持久化到图获取信息的地方,那么图的责任就是调用底层服务来进行这些更改。
  3. 为了将值传递给子组件,我们需要使用@Input()来公开一个字段,以便从父组件绑定。 在我们的代码示例中,我们像这样设置一个Todo项:
@Input() Todo: ITodoItem;
  1. 在 GraphQL 中,解析器表示如何将操作转换为数据的指令; 它们被组织为到字段的一对一映射。 另一方面,模式表示许多解析器。
  2. 要创建一个单例,我们需要做的第一件事是创建一个带有私有构造函数的类。 私有构造函数意味着只能在类内部实例化类:
export class Prefill {
  private constructor() {}
}

我们需要做的下一件事是添加一个字段来保存对类实例的引用,然后提供一个公共静态属性来访问该实例。 public 属性将负责实例化类,如果它不是可用的,这样我们就总是能够访问它:

private static prefill: Prefill;
public static get Instance(): Prefill {
  return this.prefill || (this.prefill = new this());
}

第六章

  1. 使用io.emit,我们可以向所有连接的客户端发送消息。
  2. 如果我们想要向一个特定房间的所有用户发送消息,我们会使用如下内容,我们说我们要向哪个房间发送消息,然后使用emit设置eventmessage:
io.to('room').emit('event', 'message');
  1. 要将消息发送给除发送方外的所有用户,我们需要广播消息:
socket.broadcast.emit('broadcast', 'my message');
  1. 有些特定的事件名称不能用作消息,因为它们对 Socket.IO 有特殊的含义,因此受到了限制。 这些都是error,connect,disconnect,disconnecting,newListener,removeListener,pingpong
  2. 套接字。 IO 是由许多不同的协作技术组成的,其中一种叫做 Engine.IO。 这提供了底层传输机制。 当连接时,它使用的第一种连接类型是 HTTP 长轮询,这是一种快速有效的打开传输机制。 在空闲时间,Socket。 IO 尝试确定传输是否可以被转换到套接字,如果它可以使用套接字,它将无缝且无形地升级传输以使用套接字。 就客户端而言,自 Engine 以来,它们连接迅速,消息可靠。 IO 部分建立连接,即使存在防火墙和负载平衡器。

第七章

  1. @Component定义中,我们使用host将我们想要处理的宿主事件映射到相关的 Angular 方法。 例如,在我们的MapViewComponent中,我们使用以下组件定义将window load事件映射到Loaded方法:
@Component({
  selector: 'atp-map-view',
  templateUrl: './map-view.component.html',
  styleUrls: ['./map-view.component.scss'],
  host: {
    '(window:load)' : 'Loaded()'
  }
})
  1. 纬度和经度是地理术语,用来确定某物在地球上的确切位置。 纬度告诉我们某物到赤道的南北向多远,赤道为 0; 正数表示我们在赤道以北,负数表示我们从赤道向南。 经度告诉我们,我们从东到西距离地球的垂直中心线有多远。按照惯例,这条中心线穿过伦敦的格林威治。 同样,如果我们向东移动,数字是正的,而向西移动则意味着数字是负的。
  2. 将由纬度和经度表示的位置转换为地址的操作称为反向地理编码。
  3. 我们使用 Firestore 数据库(谷歌的 Firebase 云服务的一部分)来保存数据。

第八章

  1. 容器是一个正在运行的实例,它接收运行应用所需的各种软件片段。 这是我们的起点; 容器是从映像构建的,您可以自己构建或从中央 Docker 数据库下载映像。 容器可以向其他容器(如主机操作系统)开放,甚至可以使用端口和卷向更广泛的世界开放。 容器的一大卖点是它易于设置和创建,并且可以快速停止和启动。

  2. 当我们启动 Docker 容器时,我们讨论了实现这一点的两种方法。 第一种方法是结合使用docker builddocker run启动服务:

docker build -t ohanlon/addresses .
docker run -p 17171:3000 -d ohanlon/addresses

使用-d表示它在分离并在后台静默运行时不会阻塞控制台。 这允许我们一起运行一组这些命令。 在下载中,你会发现我创建了一个批处理文件,在 Windows 上像这样启动它们。

第二种方法,也是我推荐的方法,使用 Docker 组合。 在我们的示例中,我们创建了一个用于将微服务分组的docker-compose.yml文件。 要运行我们的合成文件,我们需要使用以下命令:

docker-compose up
  1. 如果我们使用docker run来启动容器,我们可以使用-p开关指定容器内部的端口。 将端口3000映射为17171的示例如下:
docker run -p 17171:3000 -d ohanlon/addresses

当我们使用 Docker 组合时,我们在docker-compose.yml文件中指定端口重新映射。

  1. Swagger 为我们提供了许多有用的功能。 我们可以用它来创建 API 文档、创建 API 原型、自动生成代码,以及进行 API 测试。
  2. 当 React 方法不能看到状态时,我们有两个选项。 我们可以使用胖箭头=>,以便自动捕获this上下文,或者我们可以使用 JavaScriptbind特性绑定到正确的上下文。

第九章

  1. 虽然 TensorFlow 现在支持 TypeScript/JavaScript,但它最初是作为 Python 库发布的。 TensorFlow 的后端是用高性能 c++编写的。
  2. 有监督机器学习采用以前的学习,并使用它来处理新数据。 它使用标记的例子来学习正确的答案。 在这背后,有训练数据集,监督算法的工作,以完善他们的知识。
  3. MobileNet 是一个专家卷积神经网络(CNN),除其他外,提供预先训练的图像分类模型。
  4. MobileNetclassify方法默认返回包含分类名称和概率的三个分类。 可以通过指定要作为参数返回的分类数量来重写。
  5. 当我们想要创建我们的 Vue 应用时,我们使用以下命令:
vue create <<applicationname>>

因为我们想要创建 TypeScript 应用,所以我们选择手动选择特性,并且在特性屏幕上,我们确保我们选择了 TypeScript 作为选项。

  1. 当我们在.vue文件中创建类时,我们使用@Component将其标记为可以在 Vue 中注册的组件。

第十章

  1. JavaScript 和 c#的语法根源都可以追溯到 C,所以它们很大程度上遵循了类似的语言范式,比如使用{ }来表示操作的范围。 因为所有的 JavaScript 都是有效的 TypeScript,这意味着这里的 TypeScript 有完全相同的风格。
  2. 启动程序的方法是static Main方法。 它看起来是这样的:
public static void Main(string[] args)
{
  CreateWebHostBuilder(args).Build().Run();
}
  1. ASP。 NET Core 使用重写的.NET 版本,消除了只能在 Windows 平台上运行的限制。 这意味着 ASP 的影响范围。 NET 有了很大的发展,因为它现在可以在 Linux 平台上运行,也可以在 Windows 上运行。
  2. Discog 限制从单个 IP 发出的请求数量。 对于经过身份验证的请求,Discog 将请求速率限制为每分钟 60 次。 对于未经身份验证的请求,在大多数情况下,每分钟可以发送 25 个请求。 使用移动窗口监视请求的数量。