From 856809b476afd3cfd6ab9f65185156d39a5f87e3 Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Wed, 16 Aug 2023 16:32:58 +0900 Subject: [PATCH] fix: update origin v16.2 (#877) * update origin * migrate untranslated files * migrate small changes * migrate medium changes * migrate navigation * fix lint errors * fix patches * fix link errors --- aio-ja/content/errors/NG0203.en.md | 14 +- aio-ja/content/errors/NG0203.md | 14 +- aio-ja/content/errors/NG05104.md | 33 + .../guide/angular-compiler-options.en.md | 11 +- .../content/guide/angular-compiler-options.md | 7 - .../content/guide/aot-metadata-errors.en.md | 2 +- .../guide/architecture-next-steps.en.md | 2 +- .../content/guide/architecture-next-steps.md | 2 +- aio-ja/content/guide/component-overview.en.md | 8 +- aio-ja/content/guide/component-overview.md | 12 +- .../guide/dependency-injection-context.md | 63 + .../guide/dependency-injection-overview.en.md | 6 + .../guide/dependency-injection-overview.md | 6 + .../content/guide/dependency-injection.en.md | 9 + aio-ja/content/guide/dependency-injection.md | 9 + aio-ja/content/guide/deprecations.md | 7 + .../content/guide/developer-guide-overview.md | 2 +- aio-ja/content/guide/doc-editing.md | 2 +- aio-ja/content/guide/doc-select-issue.md | 2 +- aio-ja/content/guide/docs-style-guide.md | 2 +- .../guide/dynamic-component-loader.en.md | 2 +- aio-ja/content/guide/esbuild.md | 8 +- aio-ja/content/guide/example-apps-list.md | 2 +- aio-ja/content/guide/file-structure.en.md | 2 +- aio-ja/content/guide/file-structure.md | 2 +- .../hierarchical-dependency-injection.en.md | 20 +- .../hierarchical-dependency-injection.md | 24 +- .../guide/http-server-communication.md | 2 +- aio-ja/content/guide/http-test-requests.md | 2 +- aio-ja/content/guide/http.en.md | 1058 -------------- aio-ja/content/guide/http.md | 1252 ----------------- aio-ja/content/guide/http.md.old | 1243 +++++++++------- aio-ja/content/guide/hydration.md | 16 +- .../content/guide/i18n-common-prepare.en.md | 8 +- aio-ja/content/guide/i18n-common-prepare.md | 8 +- aio-ja/content/guide/image-directive.en.md | 29 +- aio-ja/content/guide/image-directive.md | 29 +- aio-ja/content/guide/inputs-outputs.en.md | 27 + aio-ja/content/guide/inputs-outputs.md | 35 +- aio-ja/content/guide/lifecycle-hooks.en.md | 95 +- aio-ja/content/guide/lifecycle-hooks.md | 97 +- .../content/guide/localized-documentation.md | 1 - aio-ja/content/guide/npm-packages.en.md | 2 +- aio-ja/content/guide/npm-packages.md | 2 +- aio-ja/content/guide/pipes.md | 2 +- aio-ja/content/guide/releases.en.md | 2 +- aio-ja/content/guide/releases.md | 2 +- .../content/guide/router-tutorial-toh.en.md | 2 + aio-ja/content/guide/router-tutorial-toh.md | 2 + aio-ja/content/guide/router.md | 4 +- aio-ja/content/guide/rxjs-interop.md | 2 +- .../content/guide/schematics-authoring.en.md | 2 +- aio-ja/content/guide/schematics-authoring.md | 2 +- aio-ja/content/guide/security.en.md | 4 +- aio-ja/content/guide/security.md | 4 +- aio-ja/content/guide/signals.en.md | 8 +- aio-ja/content/guide/signals.md | 6 +- .../content/guide/standalone-components.en.md | 6 +- aio-ja/content/guide/standalone-components.md | 2 +- .../guide/testing-components-scenarios.en.md | 2 +- .../guide/testing-components-scenarios.md | 2 +- aio-ja/content/guide/testing-services.en.md | 4 +- aio-ja/content/guide/testing-services.md | 12 +- aio-ja/content/guide/universal.en.md | 32 +- aio-ja/content/guide/universal.md | 23 +- aio-ja/content/guide/what-is-angular.en.md | 2 +- aio-ja/content/guide/what-is-angular.md | 2 +- aio-ja/content/guide/workspace-config.en.md | 20 +- aio-ja/content/guide/workspace-config.md | 6 + aio-ja/content/marketing/README.md | 1 - aio-ja/content/marketing/contributors.json | 26 +- aio-ja/content/marketing/presskit.html | 2 +- aio-ja/content/marketing/resources.json | 6 +- aio-ja/content/navigation.en.json | 94 +- aio-ja/content/navigation.json | 87 +- aio-ja/content/start/index.en.md | 13 +- aio-ja/content/start/index.md | 11 +- aio-ja/content/start/start-data.en.md | 2 +- aio-ja/content/start/start-data.md | 2 +- .../first-app/first-app-lesson-01.en.md | 43 +- .../tutorial/first-app/first-app-lesson-01.md | 34 +- .../first-app/first-app-lesson-02.en.md | 54 +- .../tutorial/first-app/first-app-lesson-02.md | 50 +- .../first-app/first-app-lesson-03.en.md | 42 +- .../tutorial/first-app/first-app-lesson-03.md | 44 +- .../first-app/first-app-lesson-04.en.md | 29 +- .../tutorial/first-app/first-app-lesson-04.md | 31 +- .../first-app/first-app-lesson-05.en.md | 37 +- .../tutorial/first-app/first-app-lesson-05.md | 35 +- .../first-app/first-app-lesson-06.en.md | 29 +- .../tutorial/first-app/first-app-lesson-06.md | 33 +- .../first-app/first-app-lesson-07.en.md | 37 +- .../tutorial/first-app/first-app-lesson-07.md | 31 +- .../tutorial/first-app/first-app-lesson-08.md | 43 +- .../tutorial/first-app/first-app-lesson-09.md | 49 +- .../tutorial/first-app/first-app-lesson-10.md | 33 +- .../tutorial/first-app/first-app-lesson-11.md | 52 +- .../tutorial/first-app/first-app-lesson-12.md | 47 +- .../tutorial/first-app/first-app-lesson-13.md | 43 +- .../tutorial/first-app/first-app-lesson-14.md | 49 +- aio-ja/content/tutorial/first-app/index.en.md | 58 +- aio-ja/content/tutorial/first-app/index.md | 62 +- .../tutorial/tour-of-heroes/toh-pt1.en.md | 2 +- .../tutorial/tour-of-heroes/toh-pt4.en.md | 4 +- .../tutorial/tour-of-heroes/toh-pt4.md | 2 +- .../tutorial/tour-of-heroes/toh-pt6.en.md | 2 +- aio-ja/content/tutorial/tutorial-template.md | 2 +- origin | 2 +- tools/git-patch/add-japanese-search.patch | 6 +- 109 files changed, 1857 insertions(+), 3706 deletions(-) create mode 100644 aio-ja/content/errors/NG05104.md create mode 100644 aio-ja/content/guide/dependency-injection-context.md delete mode 100644 aio-ja/content/guide/http.en.md delete mode 100644 aio-ja/content/guide/http.md diff --git a/aio-ja/content/errors/NG0203.en.md b/aio-ja/content/errors/NG0203.en.md index 5366bbeef1..474f86d8de 100644 --- a/aio-ja/content/errors/NG0203.en.md +++ b/aio-ja/content/errors/NG0203.en.md @@ -1,10 +1,10 @@ @name `inject()` must be called from an injection context @category runtime -@shortDescription `inject()` must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `EnvironmentInjector#runInContext`. +@shortDescription `inject()` must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. @description -You see this error when you try to use the `inject()` function outside of the allowed injection context. The injection context is available during the class creation and initialization. It is also available to functions -used with `EnvironmentInjector#runInContext`. +You see this error when you try to use the [`inject`](api/core/inject) function outside of the allowed [injection context](guide/dependency-injection-context). The injection context is available during the class creation and initialization. It is also available to functions +used with `runInInjectionContext`. In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a field initializer: @@ -23,7 +23,7 @@ export class Car { } ``` -It is also legal to call `inject` from a provider's factory: +It is also legal to call [`inject`](api/core/inject) from a provider's factory: ```typescript providers: [ @@ -35,7 +35,7 @@ providers: [ ] ``` -Calls to the `inject()` function outside of the class creation or `runInContext` will result in error. Most notably, calls to `inject()` are disallowed after a class instance was created, in methods (including lifecycle hooks): +Calls to the [`inject`](api/core/inject) function outside of the class creation or `runInInjectionContext` will result in error. Most notably, calls to `inject()` are disallowed after a class instance was created, in methods (including lifecycle hooks): ```typescript @Component({ ... }) @@ -52,7 +52,7 @@ export class CarComponent { Work backwards from the stack trace of the error to identify a place where the disallowed call to `inject()` is located. -To fix the error move the `inject()` call to an allowed place (usually a class constructor or a field initializer). +To fix the error move the [`inject`](api/core/inject) call to an allowed place (usually a class constructor or a field initializer). **Note:** If you are running in a test context, `TestBed.runInInjectionContext` will enable `inject()` to succeed. @@ -68,4 +68,4 @@ TestBed.runInInjectionContext(() => { -@reviewed 2022-05-27 +@reviewed 2023-04-11 diff --git a/aio-ja/content/errors/NG0203.md b/aio-ja/content/errors/NG0203.md index e9fff7be25..c39f5091b4 100644 --- a/aio-ja/content/errors/NG0203.md +++ b/aio-ja/content/errors/NG0203.md @@ -1,10 +1,10 @@ @name `inject()` must be called from an injection context @category runtime -@shortDescription `inject()`は、コンストラクターやファクトリ関数、フィールド初期化、あるいは `EnvironmentInjector#runInContext` で使用される関数といった、インジェクションコンテキストから呼び出す必要があります。 +@shortDescription `inject()`は、コンストラクターやファクトリ関数、フィールド初期化、あるいは `runInInjectionContext` で使用される関数といった、インジェクションコンテキストから呼び出す必要があります。 @description -このエラーは、許可されたインジェクションコンテキストの外で `inject()` 関数を使用しようとしたときに表示されます。インジェクションコンテキストは、クラスの作成時や初期化時に有効です。また、 -`EnvironmentInjector#runInContext` と共に使用される関数でも有効です。 +このエラーは、許可されたインジェクションコンテキストの外で [`inject`](api/core/inject) 関数を使用しようとしたときに表示されます。[インジェクションコンテキスト](guide/dependency-injection-context)は、クラスの作成時や初期化時に有効です。また、 +`runInInjectionContext` と共に使用される関数でも有効です。 具体的には、コンストラクターやコンストラクター引数、フィールドイニシャライザで `inject()` の呼び出しが可能です: @@ -23,7 +23,7 @@ export class Car { } ``` -また、プロバイダーのファクトリーから `inject` を呼び出すこともできます: +また、プロバイダーのファクトリーから [`inject`](api/core/inject) を呼び出すこともできます: ```typescript providers: [ @@ -35,7 +35,7 @@ providers: [ ] ``` -クラス作成時や `runInContext` の外で `inject()` 関数を呼び出すとエラーとなります。特に、クラスインスタンスが生成された後のメソッド(ライフサイクルフックを含む)では、`inject()`の呼び出しは禁止されています: +クラス作成時や `runInInjectionContext` の外で [`inject`](api/core/inject) 関数を呼び出すとエラーとなります。特に、クラスインスタンスが生成された後のメソッド(ライフサイクルフックを含む)では、`inject()`の呼び出しは禁止されています: ```typescript @Component({ ... }) @@ -52,7 +52,7 @@ export class CarComponent { エラーのスタックトレースから逆算して、禁止されている `inject()` の呼び出しがある場所を特定します。 -エラーを修正するには、`inject()`の呼び出しを許可された場所(通常はクラスのコンストラクターまたはフィールド初期化時)に移します。 +エラーを修正するには、[`inject`](api/core/inject)の呼び出しを許可された場所(通常はクラスのコンストラクターまたはフィールド初期化時)に移します。 **Note:** If you are running in a test context, `TestBed.runInInjectionContext` will enable `inject()` to succeed. @@ -68,4 +68,4 @@ TestBed.runInInjectionContext(() => { -@reviewed 2022-05-27 +@reviewed 2023-04-11 diff --git a/aio-ja/content/errors/NG05104.md b/aio-ja/content/errors/NG05104.md new file mode 100644 index 0000000000..f41075c998 --- /dev/null +++ b/aio-ja/content/errors/NG05104.md @@ -0,0 +1,33 @@ +@name Root element was not found. +@category runtime +@shortDescription Root element was not found during bootstrap. + +@description +Boostraped components are defined in the `bootstrap` property of an `@NgModule` decorator or as the first parameter of `boopstrapApplication` for standalone components. + +This error happens when Angular tries to boostrap one of these components but cannot find its corresponing node in the DOM. + +@debugging + +This issue occurs when the selector mismatches the tag + +```typescript +@Component({ + selector: 'my-app', + ... +}) +class AppComponent {} +``` + +```html + + + +``` +Replace the tag with the correct one: + +```html + + + +``` \ No newline at end of file diff --git a/aio-ja/content/guide/angular-compiler-options.en.md b/aio-ja/content/guide/angular-compiler-options.en.md index 4ba2017661..a9d9239b0b 100644 --- a/aio-ja/content/guide/angular-compiler-options.en.md +++ b/aio-ja/content/guide/angular-compiler-options.en.md @@ -26,13 +26,6 @@ For more information, see the [TypeScript Handbook](https://www.typescriptlang.o The following options are available for configuring the AOT template compiler. -### `allowEmptyCodegenFiles` - -When `true`, create all possible files even if they are empty. -Default is `false`. -Used by the Bazel build rules to simplify how Bazel rules track file dependencies. -Do not use this option outside of the Bazel rules. - ### `annotationsAs` Modifies how Angular-specific annotations are emitted to improve tree-shaking. @@ -128,9 +121,9 @@ Use to create flat modules that are packaged similarly to `@angular/core` and `@ When this option is used, the `package.json` for the library should refer to the created flat module index instead of the library index file. Produces only one `.metadata.json` file, which contains all the metadata necessary for symbols exported from the library index. -In the created `.ngfactory.js` files, the flat module index is used to import symbols. Symbols that include both the public API from the library index as well as shrouded internal symbols. +In the created `.ngfactory.js` files, the flat module index is used to import symbols. Symbols that include both the public API from the library index and shrouded internal symbols. -By default the `.ts` file supplied in the `files` field is assumed to be the library index. +By default, the `.ts` file supplied in the `files` field is assumed to be the library index. If more than one `.ts` file is specified, `libraryIndex` is used to select the file to use. If more than one `.ts` file is supplied without a `libraryIndex`, an error is produced. diff --git a/aio-ja/content/guide/angular-compiler-options.md b/aio-ja/content/guide/angular-compiler-options.md index 6db57c6003..bcdb4e407c 100644 --- a/aio-ja/content/guide/angular-compiler-options.md +++ b/aio-ja/content/guide/angular-compiler-options.md @@ -26,13 +26,6 @@ TypeScript 設定は、`extends` プロパティを使用して別のファイ 次のオプションは、AOT テンプレートコンパイラの構成に使用できます。 -### `allowEmptyCodegenFiles` - -`true` の場合、空であってもすべての可能なファイルを生成します。 -デフォルトは `false` です。 -Bazel ルールがファイルの依存関係を追跡する方法を単純化するために、Bazel ビルドルールで使用されます。 -このオプションは、Bazel ルール以外では使用しないでください。 - ### `annotationsAs` ツリーシェーキングを改善するために、Angular 固有のアノテーションの出力方法を変更します。 diff --git a/aio-ja/content/guide/aot-metadata-errors.en.md b/aio-ja/content/guide/aot-metadata-errors.en.md index aa9e9afbee..7ba5e4710b 100644 --- a/aio-ja/content/guide/aot-metadata-errors.en.md +++ b/aio-ja/content/guide/aot-metadata-errors.en.md @@ -58,7 +58,7 @@ and be wary of new or unusual TypeScript features. -The compiler encountered a referenced to a locally defined symbol that either wasn't exported or wasn't initialized. +The compiler encountered a reference to a locally defined symbol that either wasn't exported or wasn't initialized. Here's a `provider` example of the problem. diff --git a/aio-ja/content/guide/architecture-next-steps.en.md b/aio-ja/content/guide/architecture-next-steps.en.md index c4b47136a5..2fe7495119 100644 --- a/aio-ja/content/guide/architecture-next-steps.en.md +++ b/aio-ja/content/guide/architecture-next-steps.en.md @@ -33,7 +33,7 @@ Angular provides a framework for single-page applications, where most of the log Most applications still need to access a server using the `HttpClient` to access and save data. For some platforms and applications, you might also want to use the PWA \(Progressive Web App\) model to improve the user experience. -* [HTTP](guide/http): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client. +* [HTTP](guide/understanding-communicating-with-http): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client. * [Server-side rendering](guide/universal): Angular Universal generates static application pages on the server through server-side rendering \(SSR\). This allows you to run your Angular application on the server in order to improve performance and show the first page quickly on mobile and low-powered devices, and also facilitate web crawlers. * [Service workers and PWA](guide/service-worker-intro): Use a service worker to reduce dependency on the network and significantly improve the user experience. * [Web workers](guide/web-worker): Learn how to run CPU-intensive computations in a background thread. diff --git a/aio-ja/content/guide/architecture-next-steps.md b/aio-ja/content/guide/architecture-next-steps.md index 493a560608..8e55e53af7 100644 --- a/aio-ja/content/guide/architecture-next-steps.md +++ b/aio-ja/content/guide/architecture-next-steps.md @@ -33,7 +33,7 @@ Angular は、ほとんどのロジックやデータがクライアント側に ほとんどのアプリケーションはデータを取得、保存するために `HttpClient` を使ってサーバーにアクセスする必要があります。 いくつかのプラットフォームやアプリケーションでは、PWA (Progressive Web App) モデルによってユーザー体験を改善させたいかもしれません。 -* [HTTP](guide/http): HTTP クライアントを使用してサーバーと通信してデータを取得、保存し、サーバー側のアクションを呼び出します。 +* [HTTP](guide/understanding-communicating-with-http): HTTP クライアントを使用してサーバーと通信してデータを取得、保存し、サーバー側のアクションを呼び出します。 * [サーバーサイドレンダリング](guide/universal): Angular Universal は、サーバーサイドレンダリング(SSR)によってサーバー上に静的アプリケーションページを生成します。これにより、パフォーマンスを向上させ、モバイルデバイスや低パワーのデバイスで最初のページをすばやく表示し、Webクローラを手助けするために、Angular アプリケーションをサーバー上で実行できます。 * [Service WorkersとPWA](guide/service-worker-intro): service worker を使用してネットワークへの依存を減らしユーザー体験を大幅に改善します。 * [Web workers](guide/web-worker): CPU を使う処理をバックグラウンドスレッドで走らせる方法について学びます。 diff --git a/aio-ja/content/guide/component-overview.en.md b/aio-ja/content/guide/component-overview.en.md index 11e5f65db2..1d9f7622d1 100644 --- a/aio-ja/content/guide/component-overview.en.md +++ b/aio-ja/content/guide/component-overview.en.md @@ -1,6 +1,6 @@ # Angular components overview -Components are the main building block for Angular applications. +Components are the main building blocks for Angular applications. Each component consists of: * An HTML template that declares what renders on the page @@ -98,7 +98,7 @@ Every component requires a CSS *selector*. A selector instructs Angular to insta For example, consider a component `hello-world.component.ts` that defines its selector as `app-hello-world`. This selector instructs Angular to instantiate this component any time the tag `` appears in a template. -Specify a component's selector by adding a `selector` statement to the `@Component` decorator. +Specify a component's selector by adding a `selector` property to the `@Component` decorator. @@ -123,7 +123,7 @@ For example:
An Angular component requires a template defined using `template` or `templateUrl`. -You cannot have both statements in a component. +You cannot have both properties in a component.
@@ -155,4 +155,4 @@ The `styles` property takes an array of strings that contain the CSS rule declar -@reviewed 2022-02-28 +@reviewed 2023-07-29 diff --git a/aio-ja/content/guide/component-overview.md b/aio-ja/content/guide/component-overview.md index af648350d1..360f05dcbc 100644 --- a/aio-ja/content/guide/component-overview.md +++ b/aio-ja/content/guide/component-overview.md @@ -1,6 +1,7 @@ # Angular コンポーネントの概要 {@a angular-components-overview} -コンポーネントは Angular アプリケーションの主な構成要素です。各コンポーネントは次のように構成されています。 +コンポーネントは Angular アプリケーションの主な構成要素です。 +各コンポーネントは次のように構成されています。 * ページに表示するものを宣言する HTML テンプレート * 振る舞いを定義する Typescript クラス @@ -25,7 +26,8 @@ ## コンポーネントの作成 {@a creating-a-component} -コンポーネントを作成するもっとも簡単な方法は Angular CLI です。手動でコンポーネントを作成することもできます。 +コンポーネントを作成するもっとも簡単な方法は Angular CLI です。 +手動でコンポーネントを作成することもできます。 ### Angular CLI を使ったコンポーネントの作成 {@a creating-a-component-using-the-angular-cli} @@ -112,7 +114,7 @@ Angular CLI は Angular コンポーネントを作成するもっとも簡単 すべてのコンポーネントには CSS _セレクタ_ が必要です。セレクターは HTML テンプレートの中で対応するタグを見つけたらどこでも、そのコンポーネントをインスタンス化するように Angular に指示します。たとえば、`hello-world.component.ts` が `app-hello-world` というセレクターを定義しているコンポーネントを考えてみましょう。このセレクターは、テンプレートに `` タグが現れるたびに、このコンポーネントのインスタンスを作成するように Angular に指示します。 -コンポーネントのセレクターを指定するには、`@Component` デコレーターに `selector` 文を追加します。 +コンポーネントのセレクターを指定するには、`@Component` デコレーターに `selector` プロパティを追加します。 -Angular コンポーネントは、`template` または `templateUrl` で定義されたテンプレートを必要とします。コンポーネントの中で両方の記述をもつことはできません。 +Angular コンポーネントは、`template` または `templateUrl` で定義されたテンプレートを必要とします。コンポーネントの中で両方のプロパティをもつことはできません。 @@ -180,4 +182,4 @@ Angular コンポーネントは、`template` または `templateUrl` で定義 * コンポーネントのスタイルについては、[コンポーネントスタイル](guide/component-styles)を参照してください * テンプレートの詳細については、[テンプレート構文](guide/template-syntax)を参照してください -@reviewed 2021-03-18 +@reviewed 2023-07-29 diff --git a/aio-ja/content/guide/dependency-injection-context.md b/aio-ja/content/guide/dependency-injection-context.md new file mode 100644 index 0000000000..1c4227a53b --- /dev/null +++ b/aio-ja/content/guide/dependency-injection-context.md @@ -0,0 +1,63 @@ +# Injection context + +The dependency injection (DI) system relies internaly on a runtime context where the current injector is available. +This means that injectors can only work when code is executed in this context. + +The injection context is available in these situations: + +* Construction (via the `constructor`) of a class being instantiated by the DI system, such as an `@Injectable` or `@Component`. +* In the initializer for fields of such classes. +* In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`. +* In the `factory` function specified for an `InjectionToken`. +* Within a stack frame that is run in a injection context. + +Knowing when your are in an injection context, will allow you to use the [`inject`](api/core/inject) function to inject instances. + +## Class constructors + +Everytime the DI system instantiates a class, this is done in an injection context. This is being handled by the framework itself. The constructor of the class is executed in that runtime context thus allowing to inject a token using the [`inject`](api/core/inject) function. + + +class MyComponent { + private service1: Service1; + private service2: Service2 = inject(Service2); // In context + + constructor() { + this.service1 = inject(HeroService) // In context + } +} + + +## Stack frame in context + +Some APIs are designed to be run in an injection context. This is the case, for example, of the router guards. It allows the use of [`inject`](api/core/inject) to access a service within the guard function. + +Here is an example for `CanActivateFn` + +const canActivateTeam: CanActivateFn = + (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + return inject(PermissionsService).canActivate(inject(UserToken), route.params.id); + }; + + +## Run within an injection context + +When you want to run a given function in an injection context without being in one, you can do it with `runInInjectionContext`. +This requires to have access to a given injector like the `EnvironmentInjector` for example. + + + + +Note that `inject` will return an instance only if the injector can resolve the required token. + +## Asserts the context + +Angular provides `assertInInjectionContext` helper function to assert that the current context is an injection context. + +## Using DI outside of a context + +Calling [`inject`](api/core/inject) or calling `assertInInjectionContext` outside of an injection context will throw [error NG0203](/errors/NG0203). + + + +@reviewed 2023-04-11 \ No newline at end of file diff --git a/aio-ja/content/guide/dependency-injection-overview.en.md b/aio-ja/content/guide/dependency-injection-overview.en.md index cc3e09d747..bdccb526a1 100644 --- a/aio-ja/content/guide/dependency-injection-overview.en.md +++ b/aio-ja/content/guide/dependency-injection-overview.en.md @@ -33,12 +33,18 @@ You should be familiar with the Angular apps in general, and have the fundamenta
Configuring dependency providers

Describes how to configure dependencies using the providers field on the @Component and @NgModule decorators. Also describes how to use InjectionToken to provide and inject values in DI, which can be helpful when you want to use a value other than classes as dependencies.

+ + +
Injection context
+

Describes what an injection context is and how to use the DI system where you need it.

+
Hierarchical injectors

Hierarchical DI enables you to share dependencies between different parts of the application only when and if you need to. This is an advanced topic.

+ @reviewed 2022-08-02 diff --git a/aio-ja/content/guide/dependency-injection-overview.md b/aio-ja/content/guide/dependency-injection-overview.md index 9b250cfb72..04d29543be 100644 --- a/aio-ja/content/guide/dependency-injection-overview.md +++ b/aio-ja/content/guide/dependency-injection-overview.md @@ -34,11 +34,17 @@ Angularアプリケーション全般に慣れていて、コンポーネント

@Componentデコレータと@NgModuleデコレータのprovidersフィールドを使用して依存オブジェクトを設定する方法について説明します。また、クラス以外の値を依存オブジェクトとして使用したい場合に役立つ、DIで値を提供し注入するためのInjectionTokenの使用方法について説明します。

+ +
Injection context
+

Describes what an injection context is and how to use the DI system where you need it.

+ +
階層化インジェクター

階層化されたDIは、必要なときに必要なだけ、アプリケーションの異なる部分間で依存オブジェクトを共有することを可能にします。これは上級者向けのトピックです。

+ @reviewed 2022-08-02 diff --git a/aio-ja/content/guide/dependency-injection.en.md b/aio-ja/content/guide/dependency-injection.en.md index 89058ce169..b93c99b114 100644 --- a/aio-ja/content/guide/dependency-injection.en.md +++ b/aio-ja/content/guide/dependency-injection.en.md @@ -68,6 +68,15 @@ class HeroListComponent { }
+Another option is to use the [inject](api/core/inject) method: + + +@Component({ … }) +class HeroListComponent { + private service = inject(HeroService); +} + + When Angular discovers that a component depends on a service, it first checks if the injector has any existing instances of that service. If a requested service instance doesn't yet exist, the injector creates one using the registered provider, and adds it to the injector before returning the service to Angular. When all requested services have been resolved and returned, Angular can call the component's constructor with those services as arguments. diff --git a/aio-ja/content/guide/dependency-injection.md b/aio-ja/content/guide/dependency-injection.md index 056dc4df63..c52094776f 100644 --- a/aio-ja/content/guide/dependency-injection.md +++ b/aio-ja/content/guide/dependency-injection.md @@ -68,6 +68,15 @@ class HeroListComponent { } +もうひとつは、[inject](api/core/inject) を使う方法です: + + +@Component({ … }) +class HeroListComponent { + private service = inject(HeroService); +} + + Angularはコンポーネントがあるサービスに依存していることを検出すると、まずインジェクターにそのサービスの既存のインスタンスがあるかどうかをチェックします。要求されたサービスのインスタンスがまだ存在しない場合、 インジェクターは登録されたプロバイダーを使ってインスタンスを作成し、 それをインジェクターに追加してから Angular にサービスを返します。 要求されたサービスがすべて解決されて返されると、Angularはそれらのサービスを引数としてコンポーネントのコンストラクターを呼び出すことができます。 diff --git a/aio-ja/content/guide/deprecations.md b/aio-ja/content/guide/deprecations.md index b1429b2728..35197c9b1e 100644 --- a/aio-ja/content/guide/deprecations.md +++ b/aio-ja/content/guide/deprecations.md @@ -124,6 +124,13 @@ v16 - v19 | `@angular/platform-browser` | [`BrowserModule.withServerTransition`](api/platform-browser/BrowserModule#withservertransition) | v16 | v18 | | `@angular/platform-browser` | [`makeStateKey`, `StateKey` and `TransferState`](#platform-browser), symbols were moved to `@angular/core` | v16 | v18 | + +### Deprecated features that can be removed in v19 or later + +| Area | API or Feature | Deprecated in | May be removed in | +|:--- |:--- |:--- |:--- | +| `@angular/core` | `PACKAGE_ROOT_URL` | v17 | v19 | + ### Deprecated features with no planned removal version | Area | API or Feature | Deprecated in | May be removed in | diff --git a/aio-ja/content/guide/developer-guide-overview.md b/aio-ja/content/guide/developer-guide-overview.md index 84f859f3d4..e1c08a656d 100644 --- a/aio-ja/content/guide/developer-guide-overview.md +++ b/aio-ja/content/guide/developer-guide-overview.md @@ -27,7 +27,7 @@ To get the most out of these developer guides, you should review the following t

Learn about the two approaches to forms in Angular: template-driven and reactive.

- +
HTTP

Learn how to connect to a server using the HTTP client service in Angular.

diff --git a/aio-ja/content/guide/doc-editing.md b/aio-ja/content/guide/doc-editing.md index 043e477742..4feb9a1ac9 100644 --- a/aio-ja/content/guide/doc-editing.md +++ b/aio-ja/content/guide/doc-editing.md @@ -257,7 +257,7 @@ Perform these steps from a command-line tool on your local computer or in the **
**IMPORTANT**:
- Files that are not tracked by `git` are not committed or pushed to your repo on `github.com` and they do not appear in your pull request. + Files that are not tracked by `git` are not committed or pushed to your repo on `github.com`, and they do not appear in your pull request.
diff --git a/aio-ja/content/guide/doc-select-issue.md b/aio-ja/content/guide/doc-select-issue.md index 7b17322b04..c14f761910 100644 --- a/aio-ja/content/guide/doc-select-issue.md +++ b/aio-ja/content/guide/doc-select-issue.md @@ -3,7 +3,7 @@ This topic describes how to select an Angular documentation issue to fix. Angular documentation issues are stored in the **Issues** tab of the [angular/angular](https://github.com/angular/angular) repo. -Documentation issues can be identified by the `area: docs` label and they are labeled by priority. +Documentation issues can be identified by the `area: docs` label, and they are labeled by priority. You are welcome to work on [any issue](#links-to-documentation-issues) that someone else isn't already working on. If you know of a problem in the documentation that hasn't been reported, you can also [create a new documentation issue](https://github.com/angular/angular/issues/new?assignees=&labels=&template=3-docs-bug.yaml). diff --git a/aio-ja/content/guide/docs-style-guide.md b/aio-ja/content/guide/docs-style-guide.md index f6e783ece9..cf7b96d98a 100644 --- a/aio-ja/content/guide/docs-style-guide.md +++ b/aio-ja/content/guide/docs-style-guide.md @@ -21,7 +21,7 @@ The categories of Angular documentation include: | Angular documentation categories | Details | |:--- |:--- | -| [Guides](docs) | Much of what's in the [documentation section of angular.io](docs). Guides walk the reader step-by-step through tasks to demonstrate concepts and are often accompanied by a working example. These include [Getting Started](start), [Tour of Heroes](tutorial/tour-of-heroes), and pages about [Forms](guide/forms-overview), [Dependency Injection](guide/dependency-injection), and [HttpClient](guide/http). Contributing members of the community and Angular team members maintain this documentation in [Markdown](https://daringfireball.net/projects/markdown/syntax "Markdown"). | +| [Guides](docs) | Much of what's in the [documentation section of angular.io](docs). Guides walk the reader step-by-step through tasks to demonstrate concepts and are often accompanied by a working example. These include [Getting Started](start), [Tour of Heroes](tutorial/tour-of-heroes), and pages about [Forms](guide/forms-overview), [Dependency Injection](guide/dependency-injection), and [HttpClient](guide/understanding-communicating-with-http). Contributing members of the community and Angular team members maintain this documentation in [Markdown](https://daringfireball.net/projects/markdown/syntax "Markdown"). | | [API documentation](api) | Reference documents for the [Angular Application Programming Interface, or API](api). These are more succinct than guides and serve as a reference for Angular features. They are especially helpful for people already acquainted with Angular concepts. The [angular.io](https://angular.io) infrastructure generates these documents from source code and comments that contributors edit. | | [CLI documentation](cli) | The [angular.io](https://angular.io) infrastructure generates these documents from CLI source code. | diff --git a/aio-ja/content/guide/dynamic-component-loader.en.md b/aio-ja/content/guide/dynamic-component-loader.en.md index 9d555de538..8eeb51f23f 100644 --- a/aio-ja/content/guide/dynamic-component-loader.en.md +++ b/aio-ja/content/guide/dynamic-component-loader.en.md @@ -58,7 +58,7 @@ The `` element is a good choice for dynamic components because it d Take a closer look at the methods in `ad-banner.component.ts`. `AdBannerComponent` takes an array of `AdItem` objects as input, which ultimately comes from `AdService`. -`AdItem` objects specify the type of component to load and any data to bind to the component.`AdService` returns the actual ads making up the ad campaign. +`AdItem` objects specify the type of component to load and any data to bind to the component. `AdService` returns the actual ads making up the ad campaign. Passing an array of components to `AdBannerComponent` allows for a dynamic list of ads without static elements in the template. diff --git a/aio-ja/content/guide/esbuild.md b/aio-ja/content/guide/esbuild.md index 6ad416c2aa..9eb1e87897 100644 --- a/aio-ja/content/guide/esbuild.md +++ b/aio-ja/content/guide/esbuild.md @@ -164,9 +164,13 @@ Avoiding the use of modules with non-local side effects (outside of polyfills) i -### Hashed filenames for non-injected global styles/scripts +### Long build times when using Sass combined with pnpm or yarn PnP -If your application currently uses the [`inject`](guide/workspace-config#styles-and-scripts-configuration) sub-option for any global styles and scripts via the `styles` or `scripts` build options, the output file names for those styles/scripts will incorrectly contain a hash. Depending on the usage of the output files, this may cause runtime failures for your application. See the related [issue](https://github.com/angular/angular-cli/issues/25098) for more information. +Applications may have increased build times due to the need to workaround Sass resolution incompabilities when using either the pnpm or Yarn PnP package managers. +Sass files with `@import` or `@use` directives referencing a package when using either of these package managers can trigger the performance problem. + +An alternative workaround that alleviates the build time increases is in development and will be available before the build system moves to stable status. +Both the Yarn package manager in node modules mode and the `npm` package manager are not affected by this problem. ## Bug reports diff --git a/aio-ja/content/guide/example-apps-list.md b/aio-ja/content/guide/example-apps-list.md index 236d485391..9c5cb9347e 100644 --- a/aio-ja/content/guide/example-apps-list.md +++ b/aio-ja/content/guide/example-apps-list.md @@ -408,7 +408,7 @@ For more information, see [Angular documentation style guide](guide/docs-style-g Demonstrates server interaction using HTTP. -For more information, see [Communicating with backend services using HTTP](guide/http). +For more information, see [Communicating with backend services using HTTP](guide/understanding-communicating-with-http). ## Workflow diff --git a/aio-ja/content/guide/file-structure.en.md b/aio-ja/content/guide/file-structure.en.md index b55f8cf2cc..8364804cfa 100644 --- a/aio-ja/content/guide/file-structure.en.md +++ b/aio-ja/content/guide/file-structure.en.md @@ -97,7 +97,7 @@ Angular components, templates, and styles go here. | `app/app.component.html` | Defines the HTML template associated with the root `AppComponent`. | | `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. | | `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. | -| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here.

_Only generated when using the `--standalone` option._ | +| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here.

_This file is not generated when using the `--standalone` option._ | ### Application configuration files diff --git a/aio-ja/content/guide/file-structure.md b/aio-ja/content/guide/file-structure.md index 0079d28392..83595eb322 100644 --- a/aio-ja/content/guide/file-structure.md +++ b/aio-ja/content/guide/file-structure.md @@ -91,7 +91,7 @@ Angularコンポーネント、テンプレート、スタイルはここにあ | `app/app.component.html` | ルート `AppComponent` に関連付けられているHTMLテンプレートを定義します。 | | `app/app.component.css` | ルート `AppComponent` の基本CSSスタイルシートを定義します。 | | `app/app.component.spec.ts` | ルート `AppComponent` のユニットテストを定義します。 | -| `app/app.module.ts` | `AppModule` という名前のルートモジュールを定義し、Angularにアプリケーションの組み立て方法を指示します。最初は `AppComponent` のみを宣言しています。 アプリケーションにコンポーネントを追加すると、それらをここで宣言する必要があります。

_Only generated when using the `--standalone` option._ | +| `app/app.module.ts` | `AppModule` という名前のルートモジュールを定義し、Angularにアプリケーションの組み立て方法を指示します。最初は `AppComponent` のみを宣言しています。 アプリケーションにコンポーネントを追加すると、それらをここで宣言する必要があります。

_このファイルは `--standalone` オプションを使用した場合には生成されません。_ | ### アプリケーション設定ファイル {@a application-configuration-files} diff --git a/aio-ja/content/guide/hierarchical-dependency-injection.en.md b/aio-ja/content/guide/hierarchical-dependency-injection.en.md index 842803ff26..c9efa0123b 100644 --- a/aio-ja/content/guide/hierarchical-dependency-injection.en.md +++ b/aio-ja/content/guide/hierarchical-dependency-injection.en.md @@ -47,7 +47,7 @@ Angular has two injector hierarchies: The `ModuleInjector` can be configured in one of two ways by using: -* The `@Injectable()` `providedIn` property to refer to `@NgModule()`, or `root` +* The `@Injectable()` `providedIn` property to refer to `root` or `platform` * The `@NgModule()` `providers` array
@@ -273,7 +273,7 @@ class Person { ### `@Host()` `@Host()` lets you designate a component as the last stop in the injector tree when searching for providers. -Even if there is a service instance further up the tree, Angular won't continue looking +Even if there is a service instance further up the tree, Angular won't continue looking. Use `@Host()` as follows: @@ -476,7 +476,7 @@ In the logical tree, this is represented as follows: <app-child @Provide(FlowerService="🌻") @Inject(FlowerService)=>"🌻"> <!-- search ends here --> <#VIEW> <!-- search starts here --> - <h2>Parent Component</h2> + <h2>Child Component</h2> <p>Emoji from FlowerService: {{flower.emoji}} (🌻)</p> </#VIEW> </app-child> @@ -643,13 +643,13 @@ The `AnimalService` in the logical tree would look like this: <p>Emoji from AnimalService: {{animal.emoji}} (🐳)</p> </app-inspector> </div> - + + <app-inspector> + <#VIEW @Inject(AnimalService) animal=>"🐶"> + <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p> + </#VIEW> + </app-inspector> </#VIEW> - <app-inspector> - <#VIEW> - <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p> - </#VIEW> - </app-inspector> </app-child> </#VIEW> </app-root> @@ -852,7 +852,7 @@ export class ChildComponent { -When `@Host()` and `SkipSelf()` were applied to the `FlowerService`, which is in the `providers` array, the result was `null` because `@SkipSelf()` starts its search in the `` injector, but `@Host()` stops searching at `<#VIEW>` —where there is no `FlowerService` +When `@Host()` and `@SkipSelf()` were applied to the `FlowerService`, which is in the `providers` array, the result was `null` because `@SkipSelf()` starts its search in the `` injector, but `@Host()` stops searching at `<#VIEW>` —where there is no `FlowerService` In the logical tree, you can see that the `FlowerService` is visible in ``, not its `<#VIEW>`. However, the `AnimalService`, which is provided in the `AppComponent` `viewProviders` array, is visible. diff --git a/aio-ja/content/guide/hierarchical-dependency-injection.md b/aio-ja/content/guide/hierarchical-dependency-injection.md index 46800d2cfa..e18397eac8 100644 --- a/aio-ja/content/guide/hierarchical-dependency-injection.md +++ b/aio-ja/content/guide/hierarchical-dependency-injection.md @@ -50,7 +50,7 @@ Angularには2つのインジェクター階層があります。 `ModuleInjector`は、次の2ついずれかの方法で設定できます: * `@Injectable()`の`providedIn`プロパティを使用して、 -`@NgModule()`、または`root`を参照します。 +`root`、または`platform`を参照します。 * `@NgModule()`の`providers`配列を使用します。
@@ -602,7 +602,7 @@ Emoji from FlowerService: 🌻 "🌻"> <#VIEW> -

Parent Component

+

Child Component

Emoji from FlowerService: {{flower.emoji}} (🌻)

@@ -811,13 +811,13 @@ Emoji from AnimalService: 🐶 <p>Emoji from AnimalService: {{animal.emoji}} (🐳)</p> </app-inspector> </div> - + + <app-inspector> + <#VIEW @Inject(AnimalService) animal=>"🐶"> + <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p> + </#VIEW> + </app-inspector> </#VIEW> - <app-inspector> - <#VIEW> - <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p> - </#VIEW> - </app-inspector> </app-child> </#VIEW> </app-root> @@ -1029,12 +1029,8 @@ export class ChildComponent { } ``` -`@Host()`と`@SkipSelf()`が`providers` -配列にある`AnimalService`に適用された場合、 -`@SkipSelf()`は``インジェクターで検索を開始しますが、 -`@Host()`は検索を`<#VIEW>`(には`AnimalService`がありません)で停止するため、結果は`null`になります。 -論理ツリーでは、 -`AnimalService`が`<#VIEW>`ではなく``内で可視化されていることがわかります。 +`@Host()`と`@SkipSelf()`が`providers`配列にある`AnimalService`に適用された場合、`@SkipSelf()`は``インジェクターで検索を開始しますが、`@Host()`は検索を`<#VIEW>`(には`AnimalService`がありません)で停止するため、結果は`null`になります。 +論理ツリーでは、`AnimalService`が`<#VIEW>`ではなく``内で可視化されていることがわかります。 ただし、`AppComponent`の`viewProviders` 配列で提供される`AnimalService`は可視化されます。 diff --git a/aio-ja/content/guide/http-server-communication.md b/aio-ja/content/guide/http-server-communication.md index eb7c11ff28..4244ae705a 100644 --- a/aio-ja/content/guide/http-server-communication.md +++ b/aio-ja/content/guide/http-server-communication.md @@ -62,7 +62,7 @@ Important options include the *observe* and *responseType* properties. Use the `options` object to configure various other aspects of an outgoing request. In adding headers, for example, the service set the default headers using the `headers` option property. -Use the `params` property to configure a request with [TTP URL parameters, and the `reportProgress` option to listen for progress events when transferring large amounts of data. +Use the `params` property to configure a request with HTTP URL parameters, and the `reportProgress` option to listen for progress events when transferring large amounts of data.
diff --git a/aio-ja/content/guide/http-test-requests.md b/aio-ja/content/guide/http-test-requests.md index 60ecdd8e8b..8d5feefbbf 100644 --- a/aio-ja/content/guide/http-test-requests.md +++ b/aio-ja/content/guide/http-test-requests.md @@ -12,7 +12,7 @@ At the end, tests can verify that the app made no unexpected requests.
-You can run these sample tests in a live coding environment. +You can run these sample tests in a live coding environment. The tests described in this guide are in `src/testing/http-client.spec.ts`. There are also tests of an application data service that call `HttpClient` in `src/app/heroes/heroes.service.spec.ts`. diff --git a/aio-ja/content/guide/http.en.md b/aio-ja/content/guide/http.en.md deleted file mode 100644 index aa68030654..0000000000 --- a/aio-ja/content/guide/http.en.md +++ /dev/null @@ -1,1058 +0,0 @@ -# Communicating with backend services using HTTP - -Most front-end applications need to communicate with a server over the HTTP protocol, to download or upload data and access other back-end services. -Angular provides a client HTTP API for Angular applications, the `HttpClient` service class in `@angular/common/http`. - -The HTTP client service offers the following major features. - -* The ability to request [typed response objects](#typed-response) -* Streamlined [error handling](#error-handling) -* [Testability](#testing-requests) features -* Request and response [interception](#intercepting-requests-and-responses) - -## Prerequisites - -Before working with the `HttpClientModule`, you should have a basic understanding of the following: - -* TypeScript programming -* Usage of the HTTP protocol -* Angular application-design fundamentals, as described in [Angular Concepts](guide/architecture) -* Observable techniques and operators. - See the [Observables](guide/observables) guide. - -## Setup for server communication - -Before you can use `HttpClient`, you need to import the Angular `HttpClientModule`. -Most apps do so in the root `AppModule`. - - - -You can then inject the `HttpClient` service as a dependency of an application class, as shown in the following `ConfigService` example. - - - -The `HttpClient` service makes use of [observables](guide/glossary#observable "Observable definition") for all transactions. -You must import the RxJS observable and operator symbols that appear in the example snippets. -These `ConfigService` imports are typical. - - - -
- -You can run the that accompanies this guide. - -The sample app does not require a data server. -It relies on the [Angular *in-memory-web-api*](https://github.com/angular/angular/tree/main/packages/misc/angular-in-memory-web-api), which replaces the *HttpClient* module's `HttpBackend`. -The replacement service simulates the behavior of a REST-like backend. - -Look at the `AppModule` *imports* to see how it is configured. - -
- -## Requesting data from a server - -Use the [`HttpClient.get()`](api/common/http/HttpClient#get) method to fetch data from a server. -The asynchronous method sends an HTTP request, and returns an Observable that emits the requested data when the response is received. -The return type varies based on the `observe` and `responseType` values that you pass to the call. - -The `get()` method takes two arguments; the endpoint URL from which to fetch, and an *options* object that is used to configure the request. - - - -options: { - headers?: HttpHeaders | {[header: string]: string | string[]}, - observe?: 'body' | 'events' | 'response', - params?: HttpParams|{[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>}, - reportProgress?: boolean, - responseType?: 'arraybuffer'|'blob'|'json'|'text', - withCredentials?: boolean, -} - - - -Important options include the *observe* and *responseType* properties. - -* The *observe* option specifies how much of the response to return -* The *responseType* option specifies the format in which to return data - -
- -Use the `options` object to configure various other aspects of an outgoing request. -In [Adding headers](#adding-headers), for example, the service set the default headers using the `headers` option property. - -Use the `params` property to configure a request with [HTTP URL parameters](#url-params), and the `reportProgress` option to [listen for progress events](#report-progress) when transferring large amounts of data. - -
- -Applications often request JSON data from a server. -In the `ConfigService` example, the app needs a configuration file on the server, `config.json`, that specifies resource URLs. - - - -To fetch this kind of data, the `get()` call needs the following options: `{observe: 'body', responseType: 'json'}`. -These are the default values for those options, so the following examples do not pass the options object. -Later sections show some of the additional option possibilities. - -
- -The example conforms to the best practices for creating scalable solutions by defining a re-usable [injectable service](guide/glossary#service "service definition") to perform the data-handling functionality. -In addition to fetching data, the service can post-process the data, add error handling, and add retry logic. - -The `ConfigService` fetches this file using the `HttpClient.get()` method. - - - -The `ConfigComponent` injects the `ConfigService` and calls the `getConfig` service method. - -Because the service method returns an `Observable` of configuration data, the component *subscribes* to the method's return value. -The subscription callback performs minimal post-processing. -It copies the data fields into the component's `config` object, which is data-bound in the component template for display. - - - - - -### Starting the request - -For all `HttpClient` methods, the method doesn't begin its HTTP request until you call `subscribe()` on the observable the method returns. - -This is true for *all* `HttpClient` *methods*. - -
- -You should always unsubscribe from an observable when a component is destroyed. - -
- -All observables returned from `HttpClient` methods are *cold* by design. -Execution of the HTTP request is *deferred*, letting you extend the observable with additional operations such as `tap` and `catchError` before anything actually happens. - -Calling `subscribe()` triggers execution of the observable and causes `HttpClient` to compose and send the HTTP request to the server. - -Think of these observables as *blueprints* for actual HTTP requests. - -
- -In fact, each `subscribe()` initiates a separate, independent execution of the observable. -Subscribing twice results in two HTTP requests. - - - -const req = http.get<Heroes>('/api/heroes'); -// 0 requests made - .subscribe() not called. -req.subscribe(); -// 1 request made. -req.subscribe(); -// 2 requests made. - - - -
- - - -### Requesting a typed response - -Structure your `HttpClient` request to declare the type of the response object, to make consuming the output easier and more obvious. -Specifying the response type acts as a type assertion at compile time. - -
- -Specifying the response type is a declaration to TypeScript that it should treat your response as being of the given type. -This is a build-time check and doesn't guarantee that the server actually responds with an object of this type. -It is up to the server to ensure that the type specified by the server API is returned. - -
- -To specify the response object type, first define an interface with the required properties. -Use an interface rather than a class, because the response is a plain object that cannot be automatically converted to an instance of a class. - - - -Next, specify that interface as the `HttpClient.get()` call's type parameter in the service. - - - -
- -When you pass an interface as a type parameter to the `HttpClient.get()` method, use the [RxJS `map` operator](guide/rx-library#operators) to transform the response data as needed by the UI. -You can then pass the transformed data to the [async pipe](api/common/AsyncPipe). - -
- -The callback in the updated component method receives a typed data object, which is easier and safer to consume: - - - -To access properties that are defined in an interface, you must explicitly convert the plain object you get from the JSON to the required response type. -For example, the following `subscribe` callback receives `data` as an Object, and then type-casts it in order to access the properties. - - - -.subscribe(data => this.config = { - heroesUrl: (data as any).heroesUrl, - textfile: (data as any).textfile, -}); - - - - - -
- -
observe and response types
- -The types of the `observe` and `response` options are *string unions*, rather than plain strings. - - - -options: { - … - observe?: 'body' | 'events' | 'response', - … - responseType?: 'arraybuffer'|'blob'|'json'|'text', - … -} - - - -This can cause confusion. -For example: - - - -// this works -client.get('/foo', {responseType: 'text'}) - -// but this does NOT work -const options = { - responseType: 'text', -}; -client.get('/foo', options) - - - -In the second case, TypeScript infers the type of `options` to be `{responseType: string}`. -The type is too wide to pass to `HttpClient.get` which is expecting the type of `responseType` to be one of the *specific* strings. -`HttpClient` is typed explicitly this way so that the compiler can report the correct return type based on the options you provided. - -Use `as const` to let TypeScript know that you really do mean to use a constant string type: - - - -const options = { - responseType: 'text' as const, -}; -client.get('/foo', options); - - - -
- -### Reading the full response - -In the previous example, the call to `HttpClient.get()` did not specify any options. -By default, it returned the JSON data contained in the response body. - -You might need more information about the transaction than is contained in the response body. -Sometimes servers return special headers or status codes to indicate certain conditions that are important to the application workflow. - -Tell `HttpClient` that you want the full response with the `observe` option of the `get()` method: - - - -Now `HttpClient.get()` returns an `Observable` of type `HttpResponse` rather than just the JSON data contained in the body. - -The component's `showConfigResponse()` method displays the response headers as well as the configuration: - - - -As you can see, the response object has a `body` property of the correct type. - -### Making a JSONP request - -Apps can use the `HttpClient` to make [JSONP](https://en.wikipedia.org/wiki/JSONP) requests across domains when a server doesn't support [CORS protocol](https://developer.mozilla.org/docs/Web/HTTP/CORS). - -Angular JSONP requests return an `Observable`. -Follow the pattern for subscribing to observables and use the RxJS `map` operator to transform the response before using the [async pipe](api/common/AsyncPipe) to manage the results. - -In Angular, use JSONP by including `HttpClientJsonpModule` in the `NgModule` imports. -In the following example, the `searchHeroes()` method uses a JSONP request to query for heroes whose names contain the search term. - - - -/* GET heroes whose name contains search term */ -searchHeroes(term: string): Observable { - term = term.trim(); - - const heroesURL = `${this.heroesURL}?${term}`; - return this.http.jsonp(heroesUrl, 'callback').pipe( - catchError(this.handleError('searchHeroes', [])) // then handle the error - ); -} - - - -This request passes the `heroesURL` as the first parameter and the callback function name as the second parameter. -The response is wrapped in the callback function, which takes the observables returned by the JSONP method and pipes them through to the error handler. - -### Requesting non-JSON data - -Not all APIs return JSON data. -In this next example, a `DownloaderService` method reads a text file from the server and logs the file contents, before returning those contents to the caller as an `Observable`. - - - -`HttpClient.get()` returns a string rather than the default JSON because of the `responseType` option. - -The RxJS `tap` operator lets the code inspect both success and error values passing through the observable without disturbing them. - -A `download()` method in the `DownloaderComponent` initiates the request by subscribing to the service method. - - - - - -## Handling request errors - -If the request fails on the server, `HttpClient` returns an *error* object instead of a successful response. - -The same service that performs your server transactions should also perform error inspection, interpretation, and resolution. - -When an error occurs, you can obtain details of what failed in order to inform your user. -In some cases, you might also automatically [retry the request](#retry). - - - -### Getting error details - -An app should give the user useful feedback when data access fails. -A raw error object is not particularly useful as feedback. -In addition to detecting that an error has occurred, you need to get error details and use those details to compose a user-friendly response. - -Two types of errors can occur. - -* The server backend might reject the request, returning an HTTP response with a status code such as 404 or 500. - These are error *responses*. - -* Something could go wrong on the client-side such as a network error that prevents the request from completing successfully or an exception thrown in an RxJS operator. - These errors have `status` set to `0` and the `error` property contains a `ProgressEvent` object, whose `type` might provide further information. - -`HttpClient` captures both kinds of errors in its `HttpErrorResponse`. -Inspect that response to identify the error's cause. - -The following example defines an error handler in the previously defined [ConfigService](#config-service "ConfigService defined"). - - - -The handler returns an RxJS `ErrorObservable` with a user-friendly error message. -The following code updates the `getConfig()` method, using a [pipe](guide/pipes "Pipes guide") to send all observables returned by the `HttpClient.get()` call to the error handler. - - - - - -### Retrying a failed request - -Sometimes the error is transient and goes away automatically if you try again. -For example, network interruptions are common in mobile scenarios, and trying again can produce a successful result. - -The [RxJS library](guide/rx-library) offers several *retry* operators. -For example, the `retry()` operator automatically re-subscribes to a failed `Observable` a specified number of times. -*Re-subscribing* to the result of an `HttpClient` method call has the effect of reissuing the HTTP request. - -The following example shows how to pipe a failed request to the `retry()` operator before passing it to the error handler. - - - -## Sending data to a server - -In addition to fetching data from a server, `HttpClient` supports other HTTP methods such as PUT, POST, and DELETE, which you can use to modify the remote data. - -The sample app for this guide includes an abridged version of the "Tour of Heroes" example that fetches heroes and enables users to add, delete, and update them. -The following sections show examples of the data-update methods from the sample's `HeroesService`. - -### Making a POST request - -Apps often send data to a server with a POST request when submitting a form. -In the following example, the `HeroesService` makes an HTTP POST request when adding a hero to the database. - - - -The `HttpClient.post()` method is similar to `get()` in that it has a type parameter, which you can use to specify that you expect the server to return data of a given type. -The method takes a resource URL and two additional parameters: - -| Parameter | Details | -|:--- |:--- | -| body | The data to POST in the body of the request. | -| options | An object containing method options which, in this case, [specify required headers](#adding-headers). | - -The example catches errors as [described above](#error-details). - -The `HeroesComponent` initiates the actual POST operation by subscribing to the `Observable` returned by this service method. - - - -When the server responds successfully with the newly added hero, the component adds that hero to the displayed `heroes` list. - -### Making a DELETE request - -This application deletes a hero with the `HttpClient.delete` method by passing the hero's ID in the request URL. - - - -The `HeroesComponent` initiates the actual DELETE operation by subscribing to the `Observable` returned by this service method. - - - -The component isn't expecting a result from the delete operation, so it subscribes without a callback. -Even though you are not using the result, you still have to subscribe. -Calling the `subscribe()` method *executes* the observable, which is what initiates the DELETE request. - -
- -You must call `subscribe()` or nothing happens. -Just calling `HeroesService.deleteHero()` does not initiate the DELETE request. - -
- - - - -### Making a PUT request - -An app can send PUT requests using the HTTP client service. -The following `HeroesService` example, like the POST example, replaces a resource with updated data. - - - -As for any of the HTTP methods that return an observable, the caller, `HeroesComponent.update()` [must `subscribe()`](#always-subscribe "Why you must always subscribe.") to the observable returned from the `HttpClient.put()` in order to initiate the request. - -### Adding and updating headers - -Many servers require extra headers for save operations. -For example, a server might require an authorization token, or "Content-Type" header to explicitly declare the MIME type of the request body. - -##### Adding headers - -The `HeroesService` defines such headers in an `httpOptions` object that are passed to every `HttpClient` save method. - - - -##### Updating headers - -You can't directly modify the existing headers within the previous options -object because instances of the `HttpHeaders` class are immutable. -Use the `set()` method instead, to return a clone of the current instance with the new changes applied. - -The following example shows how, when an old token expires, you can update the authorization header before making the next request. - - - - - -## Configuring HTTP URL parameters - -Use the `HttpParams` class with the `params` request option to add URL query strings in your `HttpRequest`. - -The following example, the `searchHeroes()` method queries for heroes whose names contain the search term. - -Start by importing `HttpParams` class. - - - -import {HttpParams} from "@angular/common/http"; - - - - - -If there is a search term, the code constructs an options object with an HTML URL-encoded search parameter. -If the term is "cat", for example, the GET request URL would be `api/heroes?name=cat`. - -The `HttpParams` object is immutable. -If you need to update the options, save the returned value of the `.set()` method. - -You can also create HTTP parameters directly from a query string by using the `fromString` variable: - - - -const params = new HttpParams({fromString: 'name=foo'}); - - - - - -## Intercepting requests and responses - -With interception, you declare *interceptors* that inspect and transform HTTP requests from your application to a server. -The same interceptors can also inspect and transform a server's responses on their way back to the application. -Multiple interceptors form a *forward-and-backward* chain of request/response handlers. - -Interceptors can perform a variety of *implicit* tasks, from authentication to logging, in a routine, standard way, for every HTTP request/response. - -Without interception, developers would have to implement these tasks *explicitly* for each `HttpClient` method call. - -### Write an interceptor - -To implement an interceptor, declare a class that implements the `intercept()` method of the `HttpInterceptor` interface. - -Here is a do-nothing `noop` interceptor that passes the request through without touching it: - - - -The `intercept` method transforms a request into an `Observable` that eventually returns the HTTP response. -In this sense, each interceptor is fully capable of handling the request entirely by itself. - -Most interceptors inspect the request on the way in and forward the potentially altered request to the `handle()` method of the `next` object which implements the [`HttpHandler`](api/common/http/HttpHandler) interface. - - - -export abstract class HttpHandler { - abstract handle(req: HttpRequest<any>): Observable<HttpEvent<any>>; -} - - - -Like `intercept()`, the `handle()` method transforms an HTTP request into an `Observable` of [`HttpEvents`](#interceptor-events) which ultimately include the server's response. -The `intercept()` method could inspect that observable and alter it before returning it to the caller. - -This `no-op` interceptor calls `next.handle()` with the original request and returns the observable without doing a thing. - -### The `next` object - -The `next` object represents the next interceptor in the chain of interceptors. -The final `next` in the chain is the `HttpClient` backend handler that sends the request to the server and receives the server's response. - -Most interceptors call `next.handle()` so that the request flows through to the next interceptor and, eventually, the backend handler. -An interceptor *could* skip calling `next.handle()`, short-circuit the chain, and [return its own `Observable`](#caching) with an artificial server response. - -This is a common middleware pattern found in frameworks such as Express.js. - -### Provide the interceptor - -The `NoopInterceptor` is a service managed by Angular's [dependency injection (DI)](guide/dependency-injection) system. -Like other services, you must provide the interceptor class before the app can use it. - -Because interceptors are optional dependencies of the `HttpClient` service, you must provide them in the same injector or a parent of the injector that provides `HttpClient`. -Interceptors provided *after* DI creates the `HttpClient` are ignored. - -This app provides `HttpClient` in the app's root injector, as a side effect of importing the `HttpClientModule` in `AppModule`. -You should provide interceptors in `AppModule` as well. - -After importing the `HTTP_INTERCEPTORS` injection token from `@angular/common/http`, write the `NoopInterceptor` provider like this: - - - -Notice the `multi: true` option. -This required setting tells Angular that `HTTP_INTERCEPTORS` is a token for a *multiprovider* that injects an array of values, rather than a single value. - -You *could* add this provider directly to the providers array of the `AppModule`. -However, it's rather verbose and there's a good chance that you'll create more interceptors and provide them in the same way. -You must also pay [close attention to the order](#interceptor-order) in which you provide these interceptors. - -Consider creating a "barrel" file that gathers all the interceptor providers into an `httpInterceptorProviders` array, starting with this first one, the `NoopInterceptor`. - - - -Then import and add it to the `AppModule` `providers array` like this: - - - -As you create new interceptors, add them to the `httpInterceptorProviders` array and you won't have to revisit the `AppModule`. - -
- -There are many more interceptors in the complete sample code. - -
- -### Interceptor order - -Angular applies interceptors in the order that you provide them. -For example, consider a situation in which you want to handle the authentication of your HTTP requests and log them before sending them to a server. -To accomplish this task, you could provide an `AuthInterceptor` service and then a `LoggingInterceptor` service. -Outgoing requests would flow from the `AuthInterceptor` to the `LoggingInterceptor`. -Responses from these requests would flow in the other direction, from `LoggingInterceptor` back to `AuthInterceptor`. -The following is a visual representation of the process: - - - -
- -The last interceptor in the process is always the `HttpBackend` that handles communication with the server. - -
- -You cannot change the order or remove interceptors later. -If you need to enable and disable an interceptor dynamically, you'll have to build that capability into the interceptor itself. - - - -### Handling interceptor events - -Most `HttpClient` methods return observables of `HttpResponse`. -The `HttpResponse` class itself is actually an event, whose type is `HttpEventType.Response`. -A single HTTP request can, however, generate multiple events of other types, including upload and download progress events. -The methods `HttpInterceptor.intercept()` and `HttpHandler.handle()` return observables of `HttpEvent`. - -Many interceptors are only concerned with the outgoing request and return the event stream from `next.handle()` without modifying it. -Some interceptors, however, need to examine and modify the response from `next.handle()`; these operations can see all of these events in the stream. - - - -Although interceptors are capable of modifying requests and responses, the `HttpRequest` and `HttpResponse` instance properties are `readonly`, rendering them largely immutable. -They are immutable for a good reason: -An app might retry a request several times before it succeeds, which means that the interceptor chain can re-process the same request multiple times. -If an interceptor could modify the original request object, the re-tried operation would start from the modified request rather than the original. -Immutability ensures that interceptors see the same request for each try. - -
- -Your interceptor should return every event without modification unless it has a compelling reason to do otherwise. - -
- -TypeScript prevents you from setting `HttpRequest` read-only properties. - - - -// Typescript disallows the following assignment because req.url is readonly -req.url = req.url.replace('http://', 'https://'); - - - -If you must alter a request, clone it first and modify the clone before passing it to `next.handle()`. -You can clone and modify the request in a single step, as shown in the following example. - - - -The `clone()` method's hash argument lets you mutate specific properties of the request while copying the others. - -#### Modifying a request body - -The `readonly` assignment guard can't prevent deep updates and, in particular, it can't prevent you from modifying a property of a request body object. - - - -req.body.name = req.body.name.trim(); // bad idea! - - - -If you must modify the request body, follow these steps. - -1. Copy the body and make your change in the copy. -1. Clone the request object, using its `clone()` method. -1. Replace the clone's body with the modified copy. - - - -#### Clearing the request body in a clone - -Sometimes you need to clear the request body rather than replace it. -To do this, set the cloned request body to `null`. - -
- -**TIP**:
-If you set the cloned request body to `undefined`, Angular assumes you intend to leave the body as is. - -
- - - -newReq = req.clone({ … }); // body not mentioned => preserve original body -newReq = req.clone({ body: undefined }); // preserve original body -newReq = req.clone({ body: null }); // clear the body - - - -## Http interceptor use-cases - -Following are a number of common uses for interceptors. - -### Setting default headers - -Apps often use an interceptor to set default headers on outgoing requests. - -The sample app has an `AuthService` that produces an authorization token. -Here is its `AuthInterceptor` that injects that service to get the token and adds an authorization header with that token to every outgoing request: - - - -The practice of cloning a request to set new headers is so common that there's a `setHeaders` shortcut for it: - - - -An interceptor that alters headers can be used for a number of different operations, including: - -* Authentication/authorization -* Caching behavior; for example, `If-Modified-Since` -* XSRF protection - -### Logging request and response pairs - -Because interceptors can process the request and response *together*, they can perform tasks such as timing and logging an entire HTTP operation. - -Consider the following `LoggingInterceptor`, which captures the time of the request, -the time of the response, and logs the outcome with the elapsed time -with the injected `MessageService`. - - - -The RxJS `tap` operator captures whether the request succeeded or failed. -The RxJS `finalize` operator is called when the response observable either returns an error or completes and reports the outcome to the `MessageService`. - -Neither `tap` nor `finalize` touch the values of the observable stream returned to the caller. - - - -### Custom JSON parsing - -Interceptors can be used to replace the built-in JSON parsing with a custom implementation. - -The `CustomJsonInterceptor` in the following example demonstrates how to achieve this. -If the intercepted request expects a `'json'` response, the `responseType` is changed to `'text'` to disable the built-in JSON parsing. -Then the response is parsed via the injected `JsonParser`. - - - -You can then implement your own custom `JsonParser`. -Here is a custom JsonParser that has a special date reviver. - - - -You provide the `CustomParser` along with the `CustomJsonInterceptor`. - - - - - -### Caching requests - -Interceptors can handle requests by themselves, without forwarding to `next.handle()`. - -For example, you might decide to cache certain requests and responses to improve performance. -You can delegate caching to an interceptor without disturbing your existing data services. - -The `CachingInterceptor` in the following example demonstrates this approach. - - - -* The `isCacheable()` function determines if the request is cacheable. - In this sample, only GET requests to the package search API are cacheable. - -* If the request is not cacheable, the interceptor forwards the request to the next handler in the chain -* If a cacheable request is found in the cache, the interceptor returns an `of()` *observable* with the cached response, by-passing the `next` handler and all other interceptors downstream -* If a cacheable request is not in cache, the code calls `sendRequest()`. - This function forwards the request to `next.handle()` which ultimately calls the server and returns the server's response. - - - - - -
- -Notice how `sendRequest()` intercepts the response on its way back to the application. -This method pipes the response through the `tap()` operator, whose callback adds the response to the cache. - -The original response continues untouched back up through the chain of interceptors to the application caller. - -Data services, such as `PackageSearchService`, are unaware that some of their `HttpClient` requests actually return cached responses. - -
- - - - -### Using interceptors to request multiple values - -The `HttpClient.get()` method normally returns an observable that emits a single value, either the data or an error. -An interceptor can change this to an observable that emits [multiple values](guide/observables). - -The following revised version of the `CachingInterceptor` optionally returns an observable that immediately emits the cached response, sends the request on to the package search API, and emits again later with the updated search results. - - - -
- -The *cache-then-refresh* option is triggered by the presence of a custom `x-refresh` header. - -A checkbox on the `PackageSearchComponent` toggles a `withRefresh` flag, which is one of the arguments to `PackageSearchService.search()`. -That `search()` method creates the custom `x-refresh` header and adds it to the request before calling `HttpClient.get()`. - -
- -The revised `CachingInterceptor` sets up a server request whether there's a cached value or not, using the same `sendRequest()` method described [above](#send-request). -The `results$` observable makes the request when subscribed. - -* If there's no cached value, the interceptor returns `results$`. -* If there is a cached value, the code *pipes* the cached response onto `results$`. This produces a recomposed observable that emits two responses, so subscribers will see a sequence of these two responses: - * The cached response that's emitted immediately - * The response from the server, that's emitted later - - - -## Tracking and showing request progress - -Sometimes applications transfer large amounts of data and those transfers can take a long time. -File uploads are a typical example. -You can give the users a better experience by providing feedback on the progress of such transfers. - -To make a request with progress events enabled, create an instance of `HttpRequest` with the `reportProgress` option set true to enable tracking of progress events. - - - -
- -**TIP**:
-Every progress event triggers change detection, so only turn them on if you need to report progress in the UI. - -When using [`HttpClient.request()`](api/common/http/HttpClient#request) with an HTTP method, configure the method with [`observe: 'events'`](api/common/http/HttpClient#request) to see all events, including the progress of transfers. - -
- -Next, pass this request object to the `HttpClient.request()` method, which returns an `Observable` of `HttpEvents` \(the same events processed by [interceptors](#interceptor-events)\). - - - -The `getEventMessage` method interprets each type of `HttpEvent` in the event stream. - - - -
- -The sample app for this guide doesn't have a server that accepts uploaded files. -The `UploadInterceptor` in `app/http-interceptors/upload-interceptor.ts` intercepts and short-circuits upload requests by returning an observable of simulated events. - -
- -## Optimizing server interaction with debouncing - -If you need to make an HTTP request in response to user input, it's not efficient to send a request for every keystroke. -It's better to wait until the user stops typing and then send a request. -This technique is known as debouncing. - -Consider the following template, which lets a user enter a search term to find a package by name. -When the user enters a name in a search-box, the `PackageSearchComponent` sends a search request for a package with that name to the package search API. - - - -Here, the `keyup` event binding sends every keystroke to the component's `search()` method. - -
- -The type of `$event.target` is only `EventTarget` in the template. -In the `getValue()` method, the target is cast to an `HTMLInputElement` to let type-safe have access to its `value` property. - - - -
- -The following snippet implements debouncing for this input using RxJS operators. - - - -The `searchText$` is the sequence of search-box values coming from the user. -It's defined as an RxJS `Subject`, which means it is a multicasting `Observable` that can also emit values for itself by calling `next(value)`, as happens in the `search()` method. - -Rather than forward every `searchText` value directly to the injected `PackageSearchService`, the code in `ngOnInit()` pipes search values through three operators, so that a search value reaches the service only if it's a new value and the user stopped typing. - -| RxJS operators | Details | -|:--- |:--- | -| `debounceTime(500)`⁠ | Wait for the user to stop typing, which is 1/2 second in this case. | -| `distinctUntilChanged()` | Wait until the search text changes. | -| `switchMap()`⁠ | Send the search request to the service. | - -The code sets `packages$` to this re-composed `Observable` of search results. -The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe) and displays search results as they arrive. - -
- -See [Using interceptors to request multiple values](#cache-refresh) for more about the `withRefresh` option. - -
- -### Using the `switchMap()` operator - -The `switchMap()` operator takes a function argument that returns an `Observable`. -In the example, `PackageSearchService.search` returns an `Observable`, as other data service methods do. -If a previous search request is still in-flight, such as when the network connection is poor, the operator cancels that request and sends a new one. - -
- -**NOTE**:
-`switchMap()` returns service responses in their original request order, even if the server returns them out of order. - -
- -
- -If you think you'll reuse this debouncing logic, consider moving it to a utility function or into the `PackageSearchService` itself. - -
- -## Security: XSRF protection - -[Cross-Site Request Forgery (XSRF or CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website. -`HttpClient` supports a [common mechanism](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token) used to prevent XSRF attacks. -When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`. -Because only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker. - -By default, an interceptor sends this header on all mutating requests \(such as POST\) -to relative URLs, but not on GET/HEAD requests or on requests with an absolute URL. - -To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called `XSRF-TOKEN` on either the page load or the first GET request. -On subsequent requests the server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be sure that only code running on your domain could have sent the request. -The token must be unique for each user and must be verifiable by the server; this prevents the client from making up its own tokens. -Set the token to a digest of your site's authentication cookie with a salt for added security. - -To prevent collisions in environments where multiple Angular apps share the same domain or subdomain, give each application a unique cookie name. - -
- -*`HttpClient` supports only the client half of the XSRF protection scheme.* -Your backend service must be configured to set the cookie for your page, and to verify that the header is present on all eligible requests. -Failing to do so renders Angular's default protection ineffective. - -
- -### Configuring custom cookie/header names - -If your backend service uses different names for the XSRF token cookie or header, use `HttpClientXsrfModule.withOptions()` to override the defaults. - - - - - -## Testing HTTP requests - -As for any external dependency, you must mock the HTTP backend so your tests can simulate interaction with a remote server. -The `@angular/common/http/testing` library makes it straightforward to set up such mocking. - -Angular's HTTP testing library is designed for a pattern of testing in which the app executes code and makes requests first. -The test then expects that certain requests have or have not been made, performs assertions against those requests, and finally provides responses by "flushing" each expected request. - -At the end, tests can verify that the app made no unexpected requests. - -
- -You can run these sample tests in a live coding environment. - -The tests described in this guide are in `src/testing/http-client.spec.ts`. -There are also tests of an application data service that call `HttpClient` in `src/app/heroes/heroes.service.spec.ts`. - -
- -### Setup for testing - -To begin testing calls to `HttpClient`, import the `HttpClientTestingModule` and the mocking controller, `HttpTestingController`, along with the other symbols your tests require. - - - -Then add the `HttpClientTestingModule` to the `TestBed` and continue with the setup of the *service-under-test*. - - - -Now requests made in the course of your tests hit the testing backend instead of the normal backend. - -This setup also calls `TestBed.inject()` to inject the `HttpClient` service and the mocking controller so they can be referenced during the tests. - -### Expecting and answering requests - -Now you can write a test that expects a GET Request to occur and provides a mock response. - - - -The last step, verifying that no requests remain outstanding, is common enough for you to move it into an `afterEach()` step: - - - -#### Custom request expectations - -If matching by URL isn't sufficient, it's possible to implement your own matching function. -For example, you could look for an outgoing request that has an authorization header: - - - -As with the previous `expectOne()`, the test fails if 0 or 2+ requests satisfy this predicate. - -#### Handling more than one request - -If you need to respond to duplicate requests in your test, use the `match()` API instead of `expectOne()`. -It takes the same arguments but returns an array of matching requests. -Once returned, these requests are removed from future matching and you are responsible for flushing and verifying them. - - - -### Testing for errors - -You should test the app's defenses against HTTP requests that fail. - -Call `request.flush()` with an error message, as seen in the following example. - - - -Alternatively, call `request.error()` with a `ProgressEvent`. - - - -## Passing metadata to interceptors - -Many interceptors require or benefit from configuration. -Consider an interceptor that retries failed requests. -By default, the interceptor might retry a request three times, but you might want to override this retry count for particularly error-prone or sensitive requests. - -`HttpClient` requests contain a *context* that can carry metadata about the request. -This context is available for interceptors to read or modify, though it is not transmitted to the backend server when the request is sent. -This lets applications or other interceptors tag requests with configuration parameters, such as how many times to retry a request. - -### Creating a context token - -Angular stores and retrieves a value in the context using an `HttpContextToken`. -You can create a context token using the `new` operator, as in the following example: - - - -The lambda function `() => 3` passed during the creation of the `HttpContextToken` serves two purposes: - -1. It lets TypeScript infer the type of this token: - `HttpContextToken` - The request context is type-safe —reading a token from a request's context returns a value of the appropriate type. - -1. It sets the default value for the token. - This is the value that the request context returns if no other value was set for this token. - Using a default value avoids the need to check if a particular value is set. - -### Setting context values when making a request - -When making a request, you can provide an `HttpContext` instance, in which you have already set the context values. - - - -### Reading context values in an interceptor - -Within an interceptor, you can read the value of a token in a given request's context with `HttpContext.get()`. -If you have not explicitly set a value for the token, Angular returns the default value specified in the token. - - - -### Contexts are mutable - -Unlike most other aspects of `HttpRequest` instances, the request context is mutable and persists across other immutable transformations of the request. -This lets interceptors coordinate operations through the context. -For instance, the `RetryInterceptor` example could use a second context token to track how many errors occur during the execution of a given request: - - - - - - - - - -@reviewed 2022-02-28 diff --git a/aio-ja/content/guide/http.md b/aio-ja/content/guide/http.md deleted file mode 100644 index 025bb90806..0000000000 --- a/aio-ja/content/guide/http.md +++ /dev/null @@ -1,1252 +0,0 @@ -# HTTPによるバックエンドサービスとの通信 - -ほとんどのフロントエンドアプリケーションは、データをダウンロードやアップロードし、他のバックエンドサービスにアクセスするため、HTTPプロトコルによってサーバーと通信する必要があります。 -Angularは、Angularアプリケーション向けのHTTPクライアントのAPIとして、`@angular/common/http`内に`HttpClient`サービスクラスを提供しています。 - -HTTPクライアントサービスの主な機能は次のとおりです。 - -* [型付けされたレスポンスオブジェクト](#typed-response)を要求 -* 合理化された[エラーハンドリング](#error-handling) -* [テスタビリティ](#testing-requests) -* リクエストとレスポンスへの[インターセプション](#intercepting-requests-and-responses) - -##### 前提条件 - -`HttpClientModule`を使用する前に、次の基礎的な理解が必要です。 - -* TypeScriptプログラミング -* HTTPプロトコル -* [Angularの概念の紹介](guide/architecture)で説明されている、Angularアプリケーションのアーキテクチャ -* Observable技術とオペレーターについて。[Observables](guide/observables)ガイドを参照。 - -## サーバーとの通信の設定 - -`HttpClient`を使う前に、Angularの`HttpClientModule`をインポートする必要があります。 -ほとんどのアプリケーションはルートの`AppModule`で行います。 - - - - -そして、次の`ConfigService`の例に示すように、依存として`HttpClient`サービスをアプリケーションクラスに注入できるようになります。 - - - - -`HttpClient`サービスはすべてのトランザクションで[Observable](guide/glossary#observable "Observable definition")を使用します。サンプルのスニペットに現れるRxJS Observableとオペレーターをインポートする必要があります。これらの`ConfigService`のインポートは典型的なものです。 - - - - -
- -このガイドを達成するを実行できます。 - -サンプルアプリケーションはデータサーバーを必要としません。 -[Angular _in-memory-web-api_](https://github.com/angular/angular/tree/main/packages/misc/angular-in-memory-web-api) -に依存しています。 -これは、_HttpClient_モジュールの`HttpBackend`に取って代わります。 -この代わりのサービスはRESTのようなバックエンドの振る舞いをシミュレートしたものです。 - -それがどのように設定されているかを確認するには、`AppModule`の_imports_を見てください。 - -
- -## サーバーにデータをリクエストする - -サーバーからデータを取得するには、[`HttpClient.get()`](api/common/http/HttpClient#get)メソッドを使います。 -非同期メソッドがHTTPリクエストを送信し、レスポンスを受信すると要求されたデータを発行するObservableを返します。 -戻り値の型は呼び出し時に渡す`observe`と`responseType`の値によって変わります。 - -`get()`メソッドは2つの引数を取ります。取得元のエンドポイントURLと、リクエストの設定をするための*options* オブジェクトです。 - -``` -options: { - headers?: HttpHeaders | {[header: string]: string | string[]}, - observe?: 'body' | 'events' | 'response', - params?: HttpParams|{[param: string]: string | number | boolean | ReadonlyArray}, - reportProgress?: boolean, - responseType?: 'arraybuffer'|'blob'|'json'|'text', - withCredentials?: boolean, - } -``` - -*observe*と*responseType*プロパティは、重要なオプションです。 - -* *observe* オプションはどのくらいの量のレスポンスを返すのかを指定します。 -* *responseType* オプションはどのようなフォーマットでデータを返すのかを指定します。 - -
- -`options`オブジェクトは送信するリクエストに対して他にもさまざまな設定を行うことができます。 -たとえば、[ヘッダーの追加](#adding-headers)にあるように、サービスは `headers`オプションプロパティを使ってデフォルトのヘッダーを設定できます。 - -`params`プロパティでリクエストの[HTTP URLパラメーター](#url-params)の設定を行い、`reportProgress`オプションで大量のデータを送信するときの[リクエストの進行状況の監視](#report-progress)の設定を行うことができます。 - -
- -アプリケーションはサーバーにJSONデータを要求することがよくあります。 -`ConfigService`の例では、 -アプリケーションはリソースURLを指定する`config.json`という設定ファイルが必要です。 - - - - -この種のデータを取得するには、`get()`の呼び出し時に次のオプションが必要です: `{observe: 'body', responseType: 'json'}` 。 -これらはオプションのデフォルト値であるため、次の例ではoptionsオブジェクトを渡していません。 -追加で指定可能なオプションは、後続のセクションで説明します。 - -{@a config-service} - -この例は、データ処理機能を実行するため再利用できる[注入可能なサービス](guide/glossary#service "service definition")を定義することで、スケーラブルな解決法を生み出す上でのベストプラクティスにしたがっています。 -サービスは、データの取得に加え、データの後処理、エラー処理の追加、リトライロジックの追加が可能です。 - -`ConfigService`は`HttpClient.get()`メソッドにより、このファイルを取得します。 - - - - -`ConfigComponent`は`ConfigService`を注入し、 -`getConfig`サービスメソッドを呼び出します。 - -サービスメソッドが設定データの`Observable`を返すため、 -コンポーネントはメソッドの戻り値を*サブスクライブ*します。 -サブスクリプションのコールバックは最小限の後処理を行います。 -データフィールドの内容がコンポーネントの`config`オブジェクトにコピーされ、表示用にコンポーネントテンプレートへデータバインドされます。 - - - - - - -### Starting the request - -For all `HttpClient` methods, the method doesn't begin its HTTP request until you call `subscribe()` on the observable the method returns. - -This is true for *all* `HttpClient` *methods*. - -
- -You should always unsubscribe from an observable when a component is destroyed. - -
- -All observables returned from `HttpClient` methods are *cold* by design. -Execution of the HTTP request is *deferred*, letting you extend the observable with additional operations such as `tap` and `catchError` before anything actually happens. - -Calling `subscribe()` triggers execution of the observable and causes `HttpClient` to compose and send the HTTP request to the server. - -Think of these observables as *blueprints* for actual HTTP requests. - -
- -In fact, each `subscribe()` initiates a separate, independent execution of the observable. -Subscribing twice results in two HTTP requests. - - - -const req = http.get<Heroes>('/api/heroes'); -// 0 requests made - .subscribe() not called. -req.subscribe(); -// 1 request made. -req.subscribe(); -// 2 requests made. - - - -
- - - -### 型付けされたレスポンスをリクエストする - -`HttpClient`のリクエストを、そのレスポンスオブジェクトの型を宣言して構成すると、アウトプットをより簡単かつ明瞭に使えます。 -レスポンスの型を指定することでコンパイル時に型アサーションとして機能します。 - -
- -レスポンスの型の指定は、レスポンスを指定された型として扱うべきであるというTypeScriptへの宣言です。 -これはビルド時のチェックであり、サーバーが実際にこの型のオブジェクトでレスポンスを返すことは保証しません。サーバーAPIによって指定された型が返されることを保証するのは、サーバーの責任です。 - -
- -まず、レスポンスオブジェクトの型を指定するため、必要なプロパティを持ったインターフェースを定義してください。 -レスポンスはクラスのインスタンスに自動的に変換ができないプレーンオブジェクトであるため、クラスではなくインターフェースを使用してください。 - - - - -次に、そのインターフェースを`HttpClient.get()`呼び出しの型パラメーターとして指定してください。 - - - - -
- - インターフェースを型パラメーターとして`HttpClient.get()`メソッドに渡す際、[RxJSの`map`オペレーター](guide/rx-library#operators)を使用してUIで必要とされる形式にレスポンスデータを変換することができます。そして、変換されたデータを[asyncパイプ](api/common/AsyncPipe)に渡すことができます。 - -
- -更新されたコンポーネントメソッドのコールバックは、型付けされたデータオブジェクトを受け取ります。 -これは使用がより簡単で安全です。 - - - - -インターフェースで定義されているプロパティにアクセスするには、JSONから取得したプレーンオブジェクトを必要なレスポンスの型に明示的に変換する必要があります。 -たとえば、次の`subscribe`のコールバックは、`data`をObjectとして受け取り、プロパティにアクセスするためにそれを型キャストします。 - - - .subscribe(data => this.config = { - heroesUrl: (data as any).heroesUrl, - textfile: (data as any).textfile, - }); - - -{@a string-union-types} - -
-
*observe*と*response*の型
- -`observe`オプションと`response`オプションの型は、単なるstringではなく*string unions*です。 - -``` -options: { - ... - observe?: 'body' | 'events' | 'response', - ... - responseType?: 'arraybuffer'|'blob'|'json'|'text', - ... - } -``` -これは混乱を引き起こす可能性があります。たとえば、 - -```typescript -// これは動作する -client.get('/foo', {responseType: 'text'}) - -// これは動作しない -const options = { - responseType: 'text', -}; -client.get('/foo', options) -``` - -2つ目のケースでは、TypeScriptは`options`の型を`{responseType: string}`であると推論します。 -型が広すぎて、`responseType`の型が_特定の_文字列の1つであることを期待している`HttpClient.get`に渡すことができません。 -コンパイラが指定されたオプションに基づいて正しい戻り値型を報告できるよう、このように`HttpClient`は明示的に型付けされています。 - -`as const`を使用して、定数のstring型を使用することを本当は意図しているとTypeScriptに知らせましょう。 - -```typescript -const options = { - responseType: 'text' as const, -}; -client.get('/foo', options); -``` - -
- -### レスポンス全体の読み取り - -前の例で、`HttpClient.get()`の呼び出しでは何のオプションも指定していませんでした。デフォルトでは、レスポンスボディに含まれているJSONデータを返しました。 - -レスポンスボディに含まれているよりも多くのトランザクションに関する情報が必要になる場合があります。サーバーは、アプリケーションワークフローにとって重要な特定の状態を表すために、特別なヘッダーまたはステータスコードを返す場合があります。 - -`get()`メソッドの`observe`オプションにより、レスポンス全体が必要であることを`HttpClient`に伝えます。 - - - - -これで、`HttpClient.get()`は、ボディに含まれるJSONデータだけでなく、 `HttpResponse`型の`Observable`を返します。 - -コンポーネントの`showConfigResponse()`メソッドは、レスポンスヘッダーと設定値を表示します。 - - - - -見てのとおり、レスポンスオブジェクトは正しい型の`body`プロパティを持っています。 - -### JSONPリクエストの作成 - -サーバーが[CORSプロトコル](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)をサポートしていない場合、アプリケーションは`HttpClient`を使用してドメインをまたいで[JSONP](https://ja.wikipedia.org/wiki/JSONP)リクエストを実行できます。 - -AngularのJSONPリクエストは`Observable`を返します。 -Observableを購読するためのパターンに従い、[asyncパイプ](api/common/AsyncPipe)を使用して結果を処理する前に、RxJSの`map`オペレーターを使用してレスポンスを変換します。 - -Angularでは、`NgModule`のインポートに`HttpClientJsonpModule`を含めることで、JSONPを使用します。 -次の例では、`searchHeroes()`メソッドはJSONPリクエストを使用して、名前に検索語が含まれているヒーローをクエリします。 - - - -/* GET heroes whose name contains search term */ -searchHeroes(term: string): Observable { - term = term.trim(); - - const heroesURL = `${this.heroesURL}?${term}`; - return this.http.jsonp(heroesUrl, 'callback').pipe( - catchError(this.handleError('searchHeroes', [])) // then handle the error - ); -} - - - -このリクエストは、1つ目の引数として`heroesURL`を渡し、2つ目の引数としてコールバック関数名を渡します。 -レスポンスはコールバック関数でラップされます。そのコールバック関数は、JSONPメソッドによって返されたObservableを受け取って、パイプでエラーハンドラーに通します。 - -### JSON以外のデータをリクエストする - -すべてのAPIがJSONデータを返すわけではありません。 -この次の例では、`DownloaderService`のメソッドがサーバーからテキストファイルを読み取り、ファイルの内容をログに記録してから、それらの内容を` Observable`として呼び出し元に返します。 - - - - -`HttpClient.get()`は`responseType`オプションがあるため、デフォルトのJSONではなく文字列を返します。 - -RxJSの `tap` オペレーターにより、Obervableを通過する正常値とエラー値の双方を、コードがそれらを妨害することなく検査できます。 - -`DownloaderComponent`の`download()`メソッドは、サービスのメソッドを購読することでリクエストを開始します。 - - - - -{@a error-handling} - -## リクエストエラーの処理 - -サーバーでリクエストが失敗した場合、`HttpClient`は成功したレスポンスの代わりに_error_オブジェクトを返します。 - -サーバートランザクションを実行するのと同じサービスが、エラーの検査、解釈、および解決も実行する必要があります。 - -エラーが発生した場合、ユーザーに通知するために失敗した内容の詳細を取得できます。場合によっては、自動的に[リクエストの再試行](#retry)も可能です。 - -{@a error-details} -### エラーの詳細を取得する - -アプリケーションは、データアクセスが失敗したときに、ユーザーに役立つフィードバックを提供する必要があります。 -生のエラーオブジェクトは、フィードバックとして特に役立ちません。 -エラーが発生したことを検出することに加えて、エラーの詳細を取得し、それらの詳細を使用してユーザーフレンドリーなレスポンスを作成する必要があります。 - -2種類のエラーが発生する可能性があります。 - -* サーバーバックエンドがリクエストを拒否し、404や500などのステータスコードでHTTPレスポンスを返す場合があります。これらはエラー_レスポンス_です。 - -* 要求を正常に完了できないネットワークエラーや、RxJSオペレーター内でスローされた例外など、クライアント側で問題が発生する可能性があります。これらのエラーは`0`に設定された`status`と、`ProgressEvent`オブジェクトが含まれる`error`プロパティを持っています。`ProgressEvent`オブジェクトの`type`は詳細な情報を提供する可能性があります。 - -`HttpClient`は、`HttpErrorResponse`で両方の種類のエラーをキャプチャします。そのレスポンスを調べて、エラーの原因を特定できます。 - -次の例では、以前に定義された[ConfigService](#config-service "ConfigService defined")の中でエラーハンドラーを定義します。 - - - - -ハンドラーは、ユーザーフレンドリーなエラーメッセージとともにRxJS`ErrorObservable`を返します。 -次のコードでは、[パイプ](guide/pipes "Pipes guide")を使用し`HttpClient.get()`呼び出しによって返されたすべてのObservableをエラーハンドラーに送信するように、`getConfig()`メソッドが更新されています。 - - - - -{@a retry} -### 失敗したリクエストの再試行 - -エラーは一時的なものであり、再試行すると自動的に消える場合があります。 -たとえば、ネットワークの中断はモバイルシナリオで一般的であり、再試行すると -成功する可能性があります。 - -[RxJSライブラリ](guide/rx-library)はいくつかの_再試行_オペレーターを提供しています。 -たとえば、`retry()`オペレーターは、失敗した`Observable`を指定された回数だけ自動的に再サブスクライブします。`HttpClient`メソッド呼び出しの結果を_再サブスクライブ_すると、HTTPリクエストを再発行する効果があります。 - -次の例は、失敗したリクエストをエラーハンドラーに渡す前に、`retry()`オペレーターにパイプする方法を示しています。 - - - - - -## サーバーへのデータの送信 - -サーバーからデータを取得することに加えて、`HttpClient`はPUT、POST、DELETEなどの他のHTTPメソッドをサポートしています。これらは遠隔のデータを変更するために使用できます。 - -このガイドのサンプルアプリケーションには、 -ヒーローを取得し、ユーザーがヒーローを追加、削除、更新できる「Tour of Heroes」の例の簡略版が含まれています。 -次のセクションでは、サンプルの`HeroesService`からのデータ更新メソッドの例を示します。 - -### POSTリクエストの作成 - -多くの場合、アプリケーションはフォームを送信するときにPOSTリクエストを使用してサーバーにデータを送信します。 -次の例では、データベースにヒーローを追加するときに、`HeroesService`がHTTP POSTリクエストを実行します。 - - - - -`HttpClient.post()`メソッドは、型パラメータがあり、サーバーが特定の型のデータを返すことを期待するのを明示できるという点で、`get()`に似ています。このメソッドは、リソースURLと2つの追加パラメーターを取ります。 - -* *body* - POSTするリクエストのボディ内のデータ -* *options* - メソッドオプションを含むオブジェクト。この場合のオプションは、[必要なヘッダーを指定してします](#adding-headers)。 - -この例では、[前述](#error-details)のようにエラーを捕捉します。 - -`HeroesComponent`がこのサービスのメソッドが返す`Observable`を購読することによって、 -実際のPOST処理が開始します。 - - - - -サーバーが新しく追加されたヒーローを正常に返すと、 -コンポーネントはそのヒーローを画面に表示されている`heroes`リストに追加します。 - -### DELETEリクエストの作成 - -このアプリケーションは、リクエストURLにヒーローのIDを渡すことによって、 -`HttpClient.delete`メソッドを使用してヒーローを削除します。 - - - - -`HeroesComponent`がこのサービスのメソッドが返す`Observable`を購読することによって、 -実際のDELETE処理が開始します。 - - - - -コンポーネントは削除処理の結果を要求していないため、コールバックなしで購読します。結果を使用していなくても、購読する必要があります。`subscribe()`メソッドを呼び出すと、Observableが_実行_され、DELETEリクエストが開始します。 - -
- -_subscribe()_を呼び出さなければ何も起こりません。`HeroesService.deleteHero()`を呼び出すだけでは、DELETEリクエストは開始されません。 - -
- - - - - -### PUTリクエストの作成 - -アプリケーションは、HTTPクライアントサービスを使用してPUTリクエストを送信できます。 -次の`HeroesService`の例は、POSTの例と同様に、リソースを更新されたデータに置き換えます。 - - - - -Observableを返すHTTPメソッドについていえば、呼び出し元の`HeroesComponent.update()`はリクエストを開始するため、`HttpClient.put()`から返されたObservableを[`subscribe()`する必要があります。](#always-subscribe "Why you must always subscribe.") - -### ヘッダーの追加と更新 - -多くのサーバーでは、保存操作のために追加のヘッダーが必要です。 -たとえば、サーバーは認可トークンや、リクエスト本文のMIMEタイプを明示的に宣言するために「Content-Type」ヘッダーを必要とする場合があります。 - -##### ヘッダーの追加 {@a adding-headers} - -`HeroesService`は、`HttpClient`の保存メソッドすべてに渡される`httpOptions`オブジェクトで、 -そのようなヘッダーを定義しています。 - - - - -##### ヘッダーの更新 - -`HttpHeaders`クラスのインスタンスはイミュータブルなので、 -前述のoptionsオブジェクト内の既存のヘッダーを直接変更することはできません。 -代わりに`set()`メソッドを使用して、新しい変更が適用された現在のインスタンスのクローンを返します。 - -次の例は、古いトークンの有効期限が切れたときに、次のリクエストを行う前に認可ヘッダーを更新する方法を示しています。 - - - - -{@a url-params} - -## HTTP URLパラメーターの設定 - -URLクエリ文字列を`HttpRequest`に追加するには、`params`リクエストオプションに`HttpParams`クラスを使用します。 - -次の例では、`searchHeroes()`メソッドは、名前に検索語が含まれているヒーローをクエリします。 - -`HttpParams`クラスのインポートから始めます。 - - -import {HttpParams} from "@angular/common/http"; - - - - - -検索語がある場合、コードはHTML URLエンコードされた検索パラメーターをもつoptionsオブジェクトを作成します。 -たとえば検索語が「cat」の場合、GETリクエストのURLは`api/heroes?name=cat`になります。 - -`HttpParams`オブジェクトはイミュータブルです。optionsを更新する必要がある場合、`.set()`メソッドの戻り値を保存してください。 - -`fromString`変数を使用して、クエリ文字列から直接HTTPパラメータを作成することもできます。 - - -const params = new HttpParams({fromString: 'name=foo'}); - - - -{@a intercepting-requests-and-responses} -## リクエストとレスポンスのインターセプト - -インターセプトのために、アプリケーションからサーバーへのHTTPリクエストを検査して変換する_インターセプター_を宣言します。 -同じインターセプターが、アプリケーションに返ってくるサーバーのレスポンスを検査および変換することもできます。 -複数のインターセプターが、リクエスト/レスポンスハンドラーの_前後の_チェーンを形成します。 - -インターセプターは、すべてのHTTPリクエスト/レスポンスに対して、認証からロギングまで、さまざまな_暗黙の_タスクを型どおりの、標準的な方法で実行できます。 - -インターセプト無しでは、開発者は -各`HttpClient`メソッド呼び出しに対してこれらのタスクを_明示的に_実装する必要があります。 - -### インターセプターを書く - -インターセプターを実装するには、`HttpInterceptor`インターフェースの`intercept()`メソッドを実装するクラスを宣言します。 - -ここには、リクエストに触れずに渡すことだけする、_noop_インターセプターがあります。 - - - - -`intercept`メソッドは、リクエストを最終的にHTTPレスポンスを返す`Observable`に変換します。 -こういう意味では、各インターセプターは完全に単独でリクエストを処理することができます。 - -ほとんどのインターセプターは、途中でリクエストを検査し、[`HttpHandler`](api/common/http/HttpHandler)インターフェースを実装する`next`オブジェクトの`handle()`メソッドに変更された可能性のあるリクエストを転送します。 - -```javascript -export abstract class HttpHandler { - abstract handle(req: HttpRequest): Observable>; -} -``` - -`intercept()`と同様に、`handle()`メソッドは、HTTPリクエストを最終的にサーバーのレスポンスを含む[`HttpEvents`](#interceptor-events)の`Observable`に変換します。`intercept()`メソッドは、そのObservableを検査し、呼び出し元に返す前に変更することができます。 - -この_何もしない_インターセプターは、元のリクエストを渡して`next.handle()`を呼び出し、何もせずにObservableを返します。 - -### _next_オブジェクト - -`next`オブジェクトは、インターセプターのチェーン内の次のインターセプターを表します。 -チェーンの最後の`next`は、リクエストをサーバーに送信し、サーバーのレスポンスを受け取る`HttpClient`バックエンドハンドラーです。 - - -ほとんどのインターセプターは、`next.handle()`を呼び出して、リクエストが次のインターセプター、そして最終的にはバックエンドハンドラーに流れるようにします。 -インターセプターは、`next.handle()`の呼び出しをスキップしチェーンを近道して、人工のサーバーレスポンスで[自身の`Observable`を返す](#caching)こともできます。 - -これは、Express.jsなどのフレームワークでよく見られるミドルウェアパターンです。 - -### インターセプターを提供する - -`NoopInterceptor`は、Angularの[依存性の注入(DI)](guide/dependency-injection)システムによって管理されるサービスです。 -他のサービスと同様に、アプリケーションが使用する前にインターセプタークラスを提供する必要があります。 - -インターセプターは`HttpClient`サービスの依存オブジェクトであるため、 -`HttpClient`を提供しているのと同じインジェクター、または親インジェクターにそれらを提供する必要があります。 -DIが`HttpClient`を作成した_後に_提供されるインターセプターは無視されます。 - -このアプリケーションは、`AppModule`で`HttpClientModule`をインポートする副作用として、アプリケーションのルートインジェクターに`HttpClient`を提供しています。 -同様にインターセプターは`AppModule`の中で提供すべきです。 - -`@angular/common/http`から`HTTP_INTERCEPTORS`インジェクショントークンをインポートした後、 -次のように`NoopInterceptor`プロバイダーを記述します。 - - - - -`multi:true`オプションに注意してください。 -この必須設定は、Angularに`HTTP_INTERCEPTORS`は -単一の値ではなく値の配列を注入する_マルチプロバイダー_のトークンであることを伝えます。 - -このプロバイダーを `AppModule`のproviders配列に直接追加することができます。 -ただし、それはむしろ冗長であり、 -より多くのインターセプターを作成し、同じ方法でそれらを提供するよい方法があります。 -また、これらのインターセプターを提供する -[順序に細心の注意](#interceptor-order)を払う必要があります。 - -この最初の`NoopInterceptor`から始まる`httpInterceptorProviders`配列の中にすべてのインターセプタープロバイダーを集める「バレル」ファイルを作成することを検討してください。 - - - - -次に、それをインポートして`AppModule`の _providers配列_ に追加します。 - - - - -新しいインターセプターを作成するとき、それらを`httpInterceptorProviders`配列に追加するだけです。 -`AppModule`を開く必要はありません。 - -
- -完全なサンプルコードには、より多くのインターセプターがあります。 - -
- -### インターセプターの順番 {@a interceptor-order} - -Angularは、あなたが提供した順序でインターセプターを適用します。 -たとえば、サーバーに送信する前にHTTPリクエストの認証を処理し、ログに記録する必要がある状況を考えてみます。 このタスクを実行するには、`AuthInterceptor`サービスを提供してから、`LoggingInterceptor`サービスを提供します。 -送信リクエストは`AuthInterceptor`から`LoggingInterceptor`に流れます。 -これらのリクエストからのレスポンスは、`LoggingInterceptor`から`AuthInterceptor`へと逆方向に流れます。 -以下は、プロセスを視覚的に表したものです。 - - - -
- - プロセスの最後のインターセプターは常に、サーバーとの通信を処理する`HttpBackend`です。 - -
- -後で順序を変更したり、インターセプターを削除したりすることはできません。 -インターセプターを動的に有効または無効にする必要がある場合は、その機能をインターセプター自体に組み込む必要があります。 - -{@a interceptor-events} - -### インターセプターイベントの処理 - -ほとんどの`HttpClient`メソッドは`HttpResponse`のObservableを返します。 -`HttpResponse`クラス自体は実際にはイベントであり、その型は`HttpEventType.Response`です。 -ただし、単一のHTTPリクエストで、アップロードおよびダウンロードの進行状況イベントなど、他の型の複数のイベントが発生する可能性があります。 -`HttpInterceptor.intercept()`や`HttpHandler.handle()`は`HttpEvent`のObservableを返します。 - -多くのインターセプターは、送信リクエストのみに関係し、リクエストを変更せずに `next.handle()`からイベントストリームを返します。 -ただし、一部のインターセプターは、`next.handle()`からのレスポンスを検査して変更する必要があります。これらの操作は、ストリーム内のこれらのイベントのすべてを確認できます。 - -{@a immutability} - -インターセプターはリクエストとレスポンスを変更できますが、 -`HttpRequest`と`HttpResponse`インスタンスのプロパティは`readonly`であり、 -ほとんどイミュータブルになります。 -これらは正当な理由でイミュータブルです。アプリケーションはリクエストが成功する前に数回再試行する場合がある、すなわち、インターセプターチェーンが同じリクエストを複数回再処理する可能性があるためです。 -インターセプターが元のリクエストオブジェクトを変更できる場合、再試行された操作は、元のリクエストではなく、変更されたリクエストから開始します。イミュータビリティは、インターセプターが試行ごとに同じ要求を確認することを保証します。 - -
- - インターセプターは、やむを得ない理由がない限り、すべてのイベントを変更せず返す必要があります。 - -
- -TypeScriptが、`HttpRequest`の読み取り専用プロパティを設定できないようにしています。 - -```javascript - // req.urlがreadonlyであるため、Typescriptは次の代入を許可しない - req.url = req.url.replace('http://', 'https://'); -``` - -リクエストを変更する必要がある場合は、最初にクローンを作成し、クローンを変更してから`next.handle()`に渡します。 -次の例に示すように、リクエストを1つのステップで複製および変更できます。 - - - - -`clone()`メソッドのハッシュ引数を使用すると、リクエストの特定のプロパティを変更しながら、他のプロパティをコピーできます。 - -#### リクエストボディの変更 - -`readonly`の代入ガードは、深い更新を防ぐことはできません。特に、 -リクエストボディオブジェクトのプロパティを変更することを防ぐことはできません。 - -```javascript - req.body.name = req.body.name.trim(); // 良くないアイディア! -``` - -リクエストボディを変更する必要がある場合は、次の手順にしたがってください。 - -1. ボディをコピーして、コピーに変更を加えます。 -2. `clone()`メソッドを使用して、リクエストオブジェクトのクローンを作成します。 -3. クローンのボディを変更されたコピーに置き換えます。 - - - - -#### クローンのリクエストボディを消去する - -リクエストボディを置き換えるのではなく、消去する必要がある場合があります。 -これを行うには、複製されたリクエストボディを `null`に設定します。 - -
- -**Tip**: 複製されたリクエストボディを`undefined`に設定すると、Angularはボディをそのままにしておくつもりであると想定します。 - -
- -```javascript - newReq = req.clone({ ... }); // ボディは記載されていない => 元々のボディを保持する - newReq = req.clone({ body: undefined }); // 元々のボディを保持する - newReq = req.clone({ body: null }); // ボディを消去する -``` - -## Httpインターセプターのユースケース - -以下は、インターセプターのよくある使用法です。 - -### デフォルトのヘッダーをセットする - -アプリケーションでは、インターセプターを使用して外部へのリクエストにデフォルトのヘッダーを設定することがよくあります。 - -サンプルアプリケーションには、認可トークンを生成する`AuthService`があります。 -これは、トークンを取得するサービスを注入し、 -トークンをすべての外部へのリクエストの認可ヘッダーに追加する、`AuthInterceptor`です。 - - - - -新しいヘッダーを設定するため、リクエストのクローンを作成するというプラクティスは非常によくあるため、 -`setHeaders`ショートカットがあります。 - - - - -ヘッダーを変更するインターセプターは、次のようなさまざまな操作に使用できます。 - -* 認証/認可 -* キャッシュ動作。たとえば、`If-Modified-Since` -* XSRF保護 - -### リクエストとレスポンスのペアをロギングする - -インターセプターはリクエストとレスポンスを_一緒に_処理できるため、HTTPオペレーション全体について時間の計測やログの記録ができます。 - -次の`LoggingInterceptor`を考えてみましょう。 -これは、リクエストの時間とレスポンスの時間を取得し、 -注入された`MessageService`で経過時間とともに結果を記録します。 - - - - -RxJSの`tap`オペレーターは、リクエストが成功したか失敗したかを取得します。 -RxJSの`finalize`オペレーターは、レスポンスのObservableがエラーとなったか、完了したときに呼ばれ、その結果を`MessageService`に報告します。 - -`tap`も`finalize`も、呼び出し元に返されるObservableのストリームの値には影響を及ぼしません。 - -{@a custom-json-parser} - -### カスタムJSONパース処理 - -インターセプターを使用して、組み込みのJSONパース処理をカスタム実装に置き換えることができます。 - -次の例の`CustomJsonInterceptor`は、これを実現する方法を示しています。 -インターセプトされたリクエストが`'json'`レスポンスを期待している場合、組み込みのJSONパース処理を無効化するため、`responseType`は`'text'`に変更されます。 -次に、注入された`JsonParser`を介してレスポンスがパースされます。 - - - - -独自のカスタム`JsonParser`を実装できます。 -これは、特別なdate reviverをもつカスタムJsonParserです。 - - - - -`CustomJsonInterceptor`とともに、`CustomParser`を提供します。 - - - - - -{@a caching} -### リクエストをキャッシュする - -インターセプターは`next.handle()`に転送せずに、自分でリクエストを処理できます。 - -たとえば、パフォーマンスを向上させるために、特定のリクエストとレスポンスをキャッシュすると決めることがあるかもしれません。 -既存のデータサービスを妨げることなく、インターセプターにキャッシュを移譲できます。 - -次の例の`CachingInterceptor`はこのアプローチを示しています。 - - - - -* `isCachable()`関数はリクエストがキャッシュ可能かどうかを決定します。 -このサンプルでは、npmパッケージの検索APIに対するGETリクエストのみがキャッシュ可能です。 - -* リクエストがキャッシュ可能でない場合、インターセプターはリクエストを -チェーン内の次のハンドラーに転送します。 - -* キャッシング可能なリクエストがキャッシュ内に見つかった場合、インターセプターは -キャッシュされたレスポンスを`of()`_Observable_で返し、`next`ハンドラーおよび他のすべての下流のインターセプターをバイパスします。 - -* キャッシュ可能なリクエストがキャッシュにない場合、コードは`sendRequest()`を呼び出します。 -この関数はリクエストのクローンを`next.handle()`に転送し、最終的にサーバーを呼び出してサーバーのレスポンスを返します。 - -{@a send-request} - - - -
- -`sendRequest()`がアプリケーションに返ってくる途中の_レスポンスをインターセプトする_方法に注意してください。 -`tap()`オペレーターによりレスポンスを_パイプ_して、そのコールバックでレスポンスをキャッシュに追加します。 - -元のレスポンスは、インターセプターのチェーンを通って -アプリケーション呼び出し元にオリジナルの状態で戻ります。 - -`PackageSearchService`のようなデータサービスは、 -`HttpClient`リクエストのいくつかは実際にはキャッシュされたレスポンスを返すものがあることを知りません。 - -
- - - -### インターセプターを使用して複数の値を要求する - -`HttpClient.get()`メソッドは通常、データまたはエラーのいずれかの単一の値を発行するObservableを返します。 -インターセプターはこれを、[複数の値](guide/observables)を発行するObservableに変更できます。 - -次の修正された`CachingInterceptor`は、任意でObservableを返します。 -このObservableは、キャッシュされたレスポンスをすぐに発行し、リクエストをパッケージ検索APIに送信し、 -後で最新の検索結果を再度発行します。 - - - - -
- -_cache-then-refresh_オプションは、カスタムの`x-refresh`ヘッダーが存在するとトリガーされます。 - -`PackageSearchComponent`のチェックボックスは、`withRefresh`フラグを切り替えます。 -これは`PackageSearchService.search()`の引数の1つです。 -`search()`メソッドはカスタムの`x-refresh`ヘッダーを作成し、 -`HttpClient.get()`を呼び出す前にそれをリクエストに追加します。 - -
- -修正された`CachingInterceptor`は、[上記](#send-request)で説明したのと同じ`sendRequest()`メソッドを使用して、 -キャッシュされた値があるかどうかに関係なく、 -サーバーリクエストを設定します。 -`results$`Observableは、サブスクライブ時にリクエストを行います。 - -* キャッシュされた値がない場合、インターセプターは`results$`を返します。 -* If there is a cached value, the code *pipes* the cached response onto `results$`. This produces a recomposed observable that emits two responses, so subscribers will see a sequence of these two responses: - * The cached response that's emitted immediately - * The response from the server, that's emitted later - -{@a report-progress} - -## リクエストの進行状況の追跡と表示 - -アプリケーションが大量のデータを転送し、それらの転送に長い時間がかかる場合があります。 -ファイルのアップロードは典型的な例です。 -そのような転送の進行状況に関するフィードバックを提供することにより、ユーザーによりよい体験を提供します。 - -プログレスイベントを有効にしてリクエストを行うには、 -`reportProgress`オプションをtrueに設定して`HttpRequest`のインスタンスを作成し、プログレスイベントを追跡できるようにします。 - - - - -
- -**Tip**: すべてのプログレスイベントは変更検知をトリガーします。したがって、UIで進捗状況を本当に報告する必要がある場合にのみ、それらを有効にしてください。 - -[`HttpClient.request()`](api/common/http/HttpClient#request)でHTTPメソッドを使うときには、 -[`observe: 'events'`](api/common/http/HttpClient#request)で転送の進行を含むすべてのイベントを見るように設定してください。 - -
- -次に、このリクエストオブジェクトを`HttpClient.request()`メソッドに渡します。 -このメソッドは、[インターセプター](#interceptor-events)によって処理されたのと同じイベントである`HttpEvents`の`Observable`を返します。 - - - - -`getEventMessage`メソッドは、イベントストリーム中の各タイプの`HttpEvent`を解釈します。 - - - - -
- -このガイドのサンプルアプリケーションには、アップロードされたファイルを受け入れるサーバーがありません。 -`app/http-interceptors/upload-interceptor.ts`の`UploadInterceptor`は、 -アップロードリクエストをインターセプトしてショートサーキットし、 -シミュレートされたイベントのObservableを返します。 - -
- -## デバウンスによるサーバーとのやりとりの最適化 - -ユーザー入力に応じてHTTPリクエストを行う必要がある場合、キーストロークごとにリクエストを送信するのは効率的ではありません。 -ユーザーが入力をやめるのを待ってからリクエストを送信する方がよいでしょう。 -この手法はデバウンスとして知られています。 - -次のテンプレートについて考えてみます。このテンプレートでは、ユーザーが検索語を入力して、名前からパッケージを見つけることができます。 -ユーザーが検索ボックスに名前を入力すると、`PackageSearchComponent`は -その名前のパッケージの検索リクエストをパッケージ検索APIに送信します。 - - - - -ここでは、`keyup`イベントバインディングは、すべてのキーストロークをコンポーネントの`search()`メソッドに送信します。 - -
- -`$event.target`の型は、テンプレート内の`EventTarget`に過ぎません。 -`getValue()`メソッドでは、ターゲットが`HTMLInputElement`にキャストされ、その`value`プロパティへの型安全なアクセスが可能になります。 - - - -
- -次のスニペットは、RxJSオペレーターを使用してこの入力のデバウンスを実装します。 - - - - -`searchText$`は、ユーザーからの検索ボックス値のシーケンスです。 -これは、RxJSの`Subject`として定義されています。 -`Subject`は、`search()`メソッドで行っているように、`next(value)`を呼び出すことによって、 -自身に対して値を発行できるマルチキャスト`Observable`です。 - -すべての`searchText`値を注入された`PackageSearchService`に直接転送するのではなく、 -`ngOnInit()`のコードは、検索値を3つのオペレーターにパイプしています。これにより、検索値が新しい値でかつユーザーが入力を停止した場合にのみ、検索値がサービスに到達します。 - -* `debounceTime(500)`⁠—ユーザーが入力を停止するのを待ちます(この場合は1/2秒)。 - -* `distinctUntilChanged()`⁠—検索テキストが変わるまで待ちます。 - -* `switchMap()`⁠—検索リクエストをサービスに送信します。 - -このコードは、この再構成された検索結果の`Observable`に`packages$`を設定します。 -テンプレートは、[AsyncPipe](api/common/AsyncPipe)を使用して`packages$`をサブスクライブし、 -検索結果が届いた際に表示します。 - -
- -`withRefresh`オプションの詳細については、[インターセプターを使用して複数の値を要求する](#cache-refresh)を参照してください。 - -
- -### *switchMap()*オペレーターの使用 - -The `switchMap()`オペレーターは、`Observable`を返す関数を引数に取ります。 -たとえば、`PackageSearchService.search`は他のデータサービスメソッドと同様に`Observable`を返します。 -以前の検索リクエストがまだ実行中である場合(接続が悪い場合など)、 -オペレーターはリクエストをキャンセルして新しいリクエストを送信します。 - -サービスのレスポンスをサーバーが順不同で返したとしても、 -`switchMap()`は、元のリクエストの順序で返すことに注意してください。 - - -
- -このデバウンスロジックを再利用しようと考えるなら、 -ユーティリティ関数または `PackageSearchService`自体に移動することを検討してください。 - -
- - -## セキュリティ:XSRF保護 {@a security-xsrf-protection} - -[Cross-Site Request Forgery (XSRF or CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery)は、攻撃者が認証されたユーザーにそうとは知らずにあなたのWebサイト上のアクションを実行させる攻撃手法です。 -`HttpClient`は、XSRF攻撃を防ぐための[共通メカニズム](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token)をサポートしています。 -HTTPリクエストを実行するとき、インターセプターはクッキーからトークンを読み取り(デフォルトでは「XSRF-TOKEN」)、それをHTTPヘッダの`X-XSRF-TOKEN`として設定します。 -ドメインで実行されているコードのみがクッキーを読み取ることができるため、バックエンドはHTTPリクエストが攻撃者ではなくクライアントアプリケーションから送信されたことを確認できます。 - -デフォルトでは、インターセプターは相対URLへのすべての変更リクエスト(POSTなど)に対してこのヘッダーを送信しますが、 -GET/HEADリクエストや絶対URLには送りません。 - -これを利用するには、サーバーがページ読み込みまたは最初のGETリクエストのいずれかで、`XSRF-TOKEN`というJavaScriptで読み取れるセッションクッキーにトークンを設定する必要があります。 -その後のリクエストで、サーバーはクッキーが`X-XSRF-TOKEN`HTTPヘッダーと一致することを検証でき、よって、ドメイン上で実行されているコードだけがリクエストを送信可能だと保証できます。 -トークンは、各ユーザーごとに一意でなければならず、サーバーによって検証可能でなければなりません。これにより、クライアントは独自のトークンを作成することができなくなります。 -セキュリティを強化するために、ソルトをつけたサイトの認証クッキーのダイジェストをトークンに設定します。 - -複数のAngularアプリケーションが同じドメインまたはサブドメインを共有する環境での衝突を防ぐために、各アプリケーションに固有のクッキー名を付けましょう。 - -
- -*`HttpClient`は、XSRFプロテクションのスキームの半分であるクライアント側をサポートするのみです。* -バックエンドサービスは、ページのクッキーを設定し、 -該当するすべてのリクエストにヘッダーが存在することを検証するように構成する必要があります。 -そうでない場合、Angularのデフォルトの保護は効果がありません。 - -
- -### カスタムのクッキー/ヘッダーの名前を設定する - -バックエンドサービスがXSRFトークンのクッキーまたはヘッダーに異なる名前を使っている場合、 -`HttpClientXsrfModule.withOptions()`を使用してデフォルト設定を上書きします。 - - - - -{@a testing-requests} -## HTTPリクエストをテストする {@a testing-http-requests} - -外部依存と同様に、テストがリモートサーバーとのやりとりをシミュレートできるようにするには、HTTPバックエンドをモックする必要があります。 -`@angular/common/http/testing`ライブラリでは、そのようなモッキングを簡単に設定できます。 - -AngularのHTTPテスティングライブラリは、アプリケーションがコードを実行して最初にリクエストを行うテストパターンに向けて設計されています。 -テストは特定のリクエストが作成されたかどうかを期待し、 -リクエストに対してアサーションを実行し、 -最終的に期待された各リクエストを「フラッシュ」することによってレスポンスを提供します。 - -最後に、期待しないリクエストをしていないことを確認できます。 - -
- -ライブコーディング環境で -これらのサンプルテストを実行できます。 - -このガイドで説明されているテストは、`src/testing/http-client.spec.ts`にあります。 -`src/app/heroes/heroes.service.spec.ts`に -`HttpClient`を呼び出すアプリケーションデータサービスのテストもあります。 - -
- -### テストのセットアップ - -`HttpClient`への呼び出しをテストするには、 -`HttpClientTestingModule`とモックコントローラ`HttpTestingController`を、 -テストに必要な他のシンボルと共にインポートしてください。 - - - - -次に`HttpClientTestingModule`を`TestBed`に追加し、 -_テスト環境下のサービス_の設定を続けます。 - - - - -これで、テストの過程で行われたリクエストは、通常のバックエンドの代わりにテストバックエンドにヒットします。 - -この設定では`TestBed.inject()`を呼び出して`HttpClient`サービスとモックコントローラを注入し、 -テスト中に参照できるようにします。 - -### リクエストの期待と応答 - -これで、GETリクエストの発生を期待し、モックレスポンスを提供するテストを作成できます。 - - - - -最後に残ったステップは、未解決のリクエストが残っていないことを確認することです。これは、`afterEach()`ステップに移動して行うことが一般的です。 - - - - -#### カスタムリクエストの期待 - -URLによる照合では不十分な場合は、独自の照合機能を実装することができます。 -たとえば、認可ヘッダーをもつ外部へのリクエストを検索できます。 - - - - -以前の`expectOne()`と同様に、 -0または2以上のリクエストがこの条件を満たしていれば、テストは失敗します。 - -#### 複数のリクエストの処理 - -テストで重複したリクエストに応答する必要がある場合は、`expectOne()`の代わりに`match()`APIを使用してください。 -同じ引数をとりますが、一致するリクエストの配列を返します。 -これらのリクエストは一度返されると、その後の照合から削除され、 -それらをフラッシュして検証する必要があります。 - - - - -### エラーのテスト - -失敗したHTTPリクエストに対するアプリケーションの防御をテストするべきです。 - -次の例に示すように、エラーメッセージと共に`request.flush()`を呼び出します。 - - - - -あるいは、`ProgressEvent`と共に`request.error()`を呼び出すこともできます。 - - - - - -## メタデータをインターセプターに渡す - -多くのインターセプターは、設定を必要とするか、設定から恩恵を受けます。失敗したリクエストを再試行するインターセプターについて考えてみます。 -デフォルトでは、インターセプターはリクエストを3回再試行してよいですが、特にエラーが発生しやすいリクエストや機密性の高いリクエストの場合は、この再試行回数を上書きしたくなるでしょう。 - -`HttpClient`リクエストには、リクエストに関するメタデータを運ぶことができる_コンテキスト_が含まれています。 -このコンテキストは、インターセプターが読み取りまたは変更するために使用できますが、リクエスト送信時にバックエンドサーバーには送信されません。 -これにより、アプリケーションまたは他のインターセプターは、リクエストに対しリクエストを再試行する回数などの設定パラメーターを付加できます。 - -### コンテキストトークンの作成 - -Angularは、`HttpContextToken`を使用してコンテキスト内への値の格納とコンテキストからの値の取得を行います。 -次の例のように、`new`オペレーターを使用してコンテキストトークンを作成できます。 - - - -`HttpContextToken`の作成中に渡されるラムダ関数`() => 3`は2つの目的を果たします。 - -1. このトークンの型を、`HttpContextToken`とTypeScriptが推論できるようにします。 - リクエストコンテキストは型安全です。—リクエストのコンテキストからトークンを読み取ると、適切な型の値が返されます。 - -1. トークンのデフォルト値を設定します。 - これは、このトークンに他の値が設定されていない場合にリクエストコンテキストが返す値です。 - デフォルト値を使用すると、個々の値が設定されているかどうかを確認する必要がなくなります。 - -### リクエスト作成時にコンテキスト値を設定する - -リクエストを作成するときに、`HttpContext`インスタンスを提供できます。これにはコンテキスト値を設定済みです。 - - - -### インターセプターでのコンテキスト値の読み取り - -インターセプター内では、`HttpContext.get()`を使用して、与えられたリクエストのコンテキストでトークンの値を読み取ることができます。 -トークンの値を明示的に設定していない場合、Angularはトークンに指定されたデフォルト値を返します。 - - - -### コンテキストはミュータブル - -`HttpRequest`インスタンスの他の多くの性質とは異なり、リクエストコンテキストはミュータブルであり、リクエストの他のイミュータブルな変換にまたがって持続します。 -これにより、インターセプターはコンテキストを介してオペレーターを協調して動作させることができます。 -たとえば、`RetryInterceptor`の例では、2番目のコンテキストトークンを使用して、特定のリクエストの実行中に発生したエラーの数を追跡できます。 - - diff --git a/aio-ja/content/guide/http.md.old b/aio-ja/content/guide/http.md.old index 281a9d90ec..025bb90806 100644 --- a/aio-ja/content/guide/http.md.old +++ b/aio-ja/content/guide/http.md.old @@ -1,202 +1,333 @@ -# HttpClient +# HTTPによるバックエンドサービスとの通信 -ほとんどのフロントエンドアプリケーションは、HTTPプロトコルを使用してバックエンドサービスと通信します。モダンブラウザは、HTTPリクエストを行うための2つのAPIをサポートしています。`XMLHttpRequest`インターフェースと`fetch()`APIです。 +ほとんどのフロントエンドアプリケーションは、データをダウンロードやアップロードし、他のバックエンドサービスにアクセスするため、HTTPプロトコルによってサーバーと通信する必要があります。 +Angularは、Angularアプリケーション向けのHTTPクライアントのAPIとして、`@angular/common/http`内に`HttpClient`サービスクラスを提供しています。 -`@angular/common/http`の`HttpClient`は、Angularアプリケーション用のシンプルなクライアントHTTP APIを提供します。 -これはブラウザによって公開される`XMLHttpRequest`インターフェースに依存します。 -さらに`HttpClient`の利点としては、テスト機能、リクエストとレスポンスオブジェクトの型付け、リクエストとレスポンスのインターセプト、`Observable`のAPI、そして合理化されたエラー処理が含まれます。 +HTTPクライアントサービスの主な機能は次のとおりです。 -このガイドに付属のはその場で実行できます。 +* [型付けされたレスポンスオブジェクト](#typed-response)を要求 +* 合理化された[エラーハンドリング](#error-handling) +* [テスタビリティ](#testing-requests) +* リクエストとレスポンスへの[インターセプション](#intercepting-requests-and-responses) -
- -サンプルアプリはデータサーバーを必要としません。 -_HttpClient_モジュールの`HttpBackend`を置き換える -[Angular _in-memory-web-api_](https://github.com/angular/in-memory-web-api/blob/master/README.md) -に依存しています。 -このサービスはRESTのようなバックエンドの動作をシミュレートします。 +##### 前提条件 -`AppModule`の_imports_を見て、それがどのように設定されているかを見てください。 +`HttpClientModule`を使用する前に、次の基礎的な理解が必要です。 -
+* TypeScriptプログラミング +* HTTPプロトコル +* [Angularの概念の紹介](guide/architecture)で説明されている、Angularアプリケーションのアーキテクチャ +* Observable技術とオペレーターについて。[Observables](guide/observables)ガイドを参照。 -## セットアップ +## サーバーとの通信の設定 `HttpClient`を使う前に、Angularの`HttpClientModule`をインポートする必要があります。 -ほとんどのアプリはルート`AppModule`で行います。 +ほとんどのアプリケーションはルートの`AppModule`で行います。 - -`HttpClientModule`を`AppModule`にインポートしたら、 -次の`ConfigService`の例に示すように`HttpClient`をアプリケーションクラスに注入できるようになります。 +そして、次の`ConfigService`の例に示すように、依存として`HttpClient`サービスをアプリケーションクラスに注入できるようになります。 - +`HttpClient`サービスはすべてのトランザクションで[Observable](guide/glossary#observable "Observable definition")を使用します。サンプルのスニペットに現れるRxJS Observableとオペレーターをインポートする必要があります。これらの`ConfigService`のインポートは典型的なものです。 + + + + +
+ +このガイドを達成するを実行できます。 + +サンプルアプリケーションはデータサーバーを必要としません。 +[Angular _in-memory-web-api_](https://github.com/angular/angular/tree/main/packages/misc/angular-in-memory-web-api) +に依存しています。 +これは、_HttpClient_モジュールの`HttpBackend`に取って代わります。 +この代わりのサービスはRESTのようなバックエンドの振る舞いをシミュレートしたものです。 + +それがどのように設定されているかを確認するには、`AppModule`の_imports_を見てください。 + +
+ ## サーバーにデータをリクエストする -アプリケーションはしばしばJSONデータをサーバーに要求します。 -たとえば、リソースURLを指定するサーバーの設定ファイル`config.json`が必要になるかもしれません。 +サーバーからデータを取得するには、[`HttpClient.get()`](api/common/http/HttpClient#get)メソッドを使います。 +非同期メソッドがHTTPリクエストを送信し、レスポンスを受信すると要求されたデータを発行するObservableを返します。 +戻り値の型は呼び出し時に渡す`observe`と`responseType`の値によって変わります。 + +`get()`メソッドは2つの引数を取ります。取得元のエンドポイントURLと、リクエストの設定をするための*options* オブジェクトです。 + +``` +options: { + headers?: HttpHeaders | {[header: string]: string | string[]}, + observe?: 'body' | 'events' | 'response', + params?: HttpParams|{[param: string]: string | number | boolean | ReadonlyArray}, + reportProgress?: boolean, + responseType?: 'arraybuffer'|'blob'|'json'|'text', + withCredentials?: boolean, + } +``` + +*observe*と*responseType*プロパティは、重要なオプションです。 + +* *observe* オプションはどのくらいの量のレスポンスを返すのかを指定します。 +* *responseType* オプションはどのようなフォーマットでデータを返すのかを指定します。 + +
+`options`オブジェクトは送信するリクエストに対して他にもさまざまな設定を行うことができます。 +たとえば、[ヘッダーの追加](#adding-headers)にあるように、サービスは `headers`オプションプロパティを使ってデフォルトのヘッダーを設定できます。 - + +アプリケーションはサーバーにJSONデータを要求することがよくあります。 +`ConfigService`の例では、 +アプリケーションはリソースURLを指定する`config.json`という設定ファイルが必要です。 + + -`ConfigService`はこのファイルを`HttpClient`の`get()`メソッドでフェッチします。 +この種のデータを取得するには、`get()`の呼び出し時に次のオプションが必要です: `{observe: 'body', responseType: 'json'}` 。 +これらはオプションのデフォルト値であるため、次の例ではoptionsオブジェクトを渡していません。 +追加で指定可能なオプションは、後続のセクションで説明します。 - -`ConfigComponent`というコンポーネントは、`ConfigService`を注入し`getConfig`サービスメソッドを呼び出します。 +`ConfigComponent`は`ConfigService`を注入し、 +`getConfig`サービスメソッドを呼び出します。 +サービスメソッドが設定データの`Observable`を返すため、 +コンポーネントはメソッドの戻り値を*サブスクライブ*します。 +サブスクリプションのコールバックは最小限の後処理を行います。 +データフィールドの内容がコンポーネントの`config`オブジェクトにコピーされ、表示用にコンポーネントテンプレートへデータバインドされます。 - -サービスメソッドは構成データの`Observable`を返すので、コンポーネントはメソッドの戻り値を**購読**します。 -サブスクリプションのコールバックでは、データフィールドをコンポーネントの`config`オブジェクトにコピーします。 -このオブジェクトは、表示のためにコンポーネントのテンプレート内でデータバインドされています。 + +### Starting the request -
-
サービスを書く理由は?
+For all `HttpClient` methods, the method doesn't begin its HTTP request until you call `subscribe()` on the observable the method returns. -この例はとてもシンプルで、`Http.get()`をコンポーネント自身に書いてサービスは作りません。 -しかし実践では、データアクセスはめったにこのようなシンプルな形にはなりません。 -典型的には、データの後処理、エラー処理の追加、断続的な接続に対処するためのリトライロジックなどが必要になります。 +This is true for *all* `HttpClient` *methods*. +
+You should always unsubscribe from an observable when a component is destroyed. -このコンポーネントは、データアクセスの細分化ですぐに乱雑になります。 -コンポーネントの理解が難しくなり、テストが難しくなり、データアクセスロジックを再利用したり標準化することができなくなります。 +
+ +All observables returned from `HttpClient` methods are *cold* by design. +Execution of the HTTP request is *deferred*, letting you extend the observable with additional operations such as `tap` and `catchError` before anything actually happens. + +Calling `subscribe()` triggers execution of the observable and causes `HttpClient` to compose and send the HTTP request to the server. -そのため、このサービスのような単純なケースでも、データアクセスを別のサービスにカプセル化し、コンポーネント内のそのサービスに委任することによって、データの表示とデータアクセスを分離することがベストプラクティスです。 +Think of these observables as *blueprints* for actual HTTP requests. + +
+In fact, each `subscribe()` initiates a separate, independent execution of the observable. +Subscribing twice results in two HTTP requests. + + + +const req = http.get<Heroes>('/api/heroes'); +// 0 requests made - .subscribe() not called. +req.subscribe(); +// 1 request made. +req.subscribe(); +// 2 requests made. + +
+ + ### 型付けされたレスポンスをリクエストする `HttpClient`のリクエストを、そのレスポンスオブジェクトの型を宣言して構成すると、アウトプットをより簡単かつ明瞭に使えます。 レスポンスの型を指定することでコンパイル時に型アサーションとして機能します。 -レスポンスオブジェクトの型を指定するため、まず、必要なプロパティをもつインターフェースを定義します。 -(クラスではなくインターフェースを用います。レスポンスはクラスのインスタンスに自動的には変換されません。) +
+ +レスポンスの型の指定は、レスポンスを指定された型として扱うべきであるというTypeScriptへの宣言です。 +これはビルド時のチェックであり、サーバーが実際にこの型のオブジェクトでレスポンスを返すことは保証しません。サーバーAPIによって指定された型が返されることを保証するのは、サーバーの責任です。 + +
+ +まず、レスポンスオブジェクトの型を指定するため、必要なプロパティを持ったインターフェースを定義してください。 +レスポンスはクラスのインスタンスに自動的に変換ができないプレーンオブジェクトであるため、クラスではなくインターフェースを使用してください。 - -次に、サービス内でそのインターフェースを`HttpClient.get()`呼び出しの型パラメーターとして指定します。 +次に、そのインターフェースを`HttpClient.get()`呼び出しの型パラメーターとして指定してください。 -
- 型パラメーターとしてのインターフェースを`HttpClient.get()`メソッドに渡すとき、RxJSの`map`オペレーターを使用して、レスポンスのデータをUIで必要なように変形します。それから変形されたデータを[非同期パイプ](api/common/AsyncPipe)に渡せます。 + インターフェースを型パラメーターとして`HttpClient.get()`メソッドに渡す際、[RxJSの`map`オペレーター](guide/rx-library#operators)を使用してUIで必要とされる形式にレスポンスデータを変換することができます。そして、変換されたデータを[asyncパイプ](api/common/AsyncPipe)に渡すことができます。
-更新されたコンポーネントメソッドのコールバックは、より簡単で安全な型指定されたデータオブジェクトを受け取ります。 +更新されたコンポーネントメソッドのコールバックは、型付けされたデータオブジェクトを受け取ります。 +これは使用がより簡単で安全です。 - - -
+インターフェースで定義されているプロパティにアクセスするには、JSONから取得したプレーンオブジェクトを必要なレスポンスの型に明示的に変換する必要があります。 +たとえば、次の`subscribe`のコールバックは、`data`をObjectとして受け取り、プロパティにアクセスするためにそれを型キャストします。 -レスポンスの型を指定することは、レスポンスはその型になると予想するという、TypeScriptへの宣言です。 -これはビルド時のチェックであり、サーバーが実際にこの型のオブジェクトでレスポンスすることは保証しません。サーバーAPI指定の型が戻ることを確実にするのは、サーバーの責任です。 - -
- -インターフェースで定義されたプロパティにアクセスするには、JSONから得られたObjectを必要なレスポンスの型へ明示的に変換する必要があります。 -たとえば、次の`subscribe`のコールバックは、Objectとしての`data`を受け取り、それからそのプロパティにアクセスするために型キャストしています。 - - + .subscribe(data => this.config = { - heroesUrl: (data as any).heroesUrl, - textfile: (data as any).textfile, + heroesUrl: (data as any).heroesUrl, + textfile: (data as any).textfile, }); +{@a string-union-types} -### レスポンス全体を読む +
+
*observe*と*response*の型
-レスポンスボディはすべてのデータを返しません。場合によっては、サーバーは特別なヘッダーやステータスコードを返すことがあります。アプリケーションのワークフローに重要な特定の条件を示すためにです。 +`observe`オプションと`response`オプションの型は、単なるstringではなく*string unions*です。 -`HttpClient`に`observe`オプションをつければレスポンス全体が読めるようになります。 +``` +options: { + ... + observe?: 'body' | 'events' | 'response', + ... + responseType?: 'arraybuffer'|'blob'|'json'|'text', + ... + } +``` +これは混乱を引き起こす可能性があります。たとえば、 + +```typescript +// これは動作する +client.get('/foo', {responseType: 'text'}) + +// これは動作しない +const options = { + responseType: 'text', +}; +client.get('/foo', options) +``` + +2つ目のケースでは、TypeScriptは`options`の型を`{responseType: string}`であると推論します。 +型が広すぎて、`responseType`の型が_特定の_文字列の1つであることを期待している`HttpClient.get`に渡すことができません。 +コンパイラが指定されたオプションに基づいて正しい戻り値型を報告できるよう、このように`HttpClient`は明示的に型付けされています。 - + +### レスポンス全体の読み取り + +前の例で、`HttpClient.get()`の呼び出しでは何のオプションも指定していませんでした。デフォルトでは、レスポンスボディに含まれているJSONデータを返しました。 + +レスポンスボディに含まれているよりも多くのトランザクションに関する情報が必要になる場合があります。サーバーは、アプリケーションワークフローにとって重要な特定の状態を表すために、特別なヘッダーまたはステータスコードを返す場合があります。 + +`get()`メソッドの`observe`オプションにより、レスポンス全体が必要であることを`HttpClient`に伝えます。 + + -今度は`HttpClient.get()`は、ただのJSONデータではなく`HttpResponse`型の`Observable`を返します。 +これで、`HttpClient.get()`は、ボディに含まれるJSONデータだけでなく、 `HttpResponse`型の`Observable`を返します。 -コンポーネントの`showConfigResponse()`メソッドはレスポンスヘッダとコンフィグレーションを表示します。 +コンポーネントの`showConfigResponse()`メソッドは、レスポンスヘッダーと設定値を表示します。 - -ご覧のように、レスポンスオブジェクトは正しい型の`body`プロパティを持っています。 +見てのとおり、レスポンスオブジェクトは正しい型の`body`プロパティを持っています。 -### JSONPリクエストを作る +### JSONPリクエストの作成 -サーバーが[CORSプロトコル](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)をサポートしないときは、アプリは`HttpClient`を使用してドメイン間で[JSONP](https://en.wikipedia.org/wiki/JSONP)リクエストを行えます。 +サーバーが[CORSプロトコル](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)をサポートしていない場合、アプリケーションは`HttpClient`を使用してドメインをまたいで[JSONP](https://ja.wikipedia.org/wiki/JSONP)リクエストを実行できます。 AngularのJSONPリクエストは`Observable`を返します。 -Observableを購読するパターンに続いて、[非同期パイプ](api/common/AsyncPipe)を用いて結果を扱う前に、RxJSの`map`オペレーターを使用してレスポンスを変形します。 +Observableを購読するためのパターンに従い、[asyncパイプ](api/common/AsyncPipe)を使用して結果を処理する前に、RxJSの`map`オペレーターを使用してレスポンスを変換します。 + +Angularでは、`NgModule`のインポートに`HttpClientJsonpModule`を含めることで、JSONPを使用します。 +次の例では、`searchHeroes()`メソッドはJSONPリクエストを使用して、名前に検索語が含まれているヒーローをクエリします。 -Angularでは、`NgModule`のインポートに`HttpClientJsonpModule`を含めることでJSONPを使います。 -次の例では、`searchHeroes()`メソッドはJSONPリクエストを使って検索語句を名前に含むヒーローを探します。 + -```ts -/* 検索語句を名前に含むヒーローをGET */ +/* GET heroes whose name contains search term */ searchHeroes(term: string): Observable { term = term.trim(); - let heroesURL = `${this.heroesURL}?${term}`; + const heroesURL = `${this.heroesURL}?${term}`; return this.http.jsonp(heroesUrl, 'callback').pipe( - catchError(this.handleError('searchHeroes', [])) // それからエラーに対処する + catchError(this.handleError('searchHeroes', [])) // then handle the error ); -}; -``` +} + + -このリクエストは最初のパラメーターとして`heroesURL`を、2番目のパラメーターとしてコールバック関数の名前を渡します。 -レスポンスはそのコールバック関数にラップされ、その関数はJSONPメソッドによって戻されるObservableを受け取って、パイプでエラーハンドラーに通します。 +このリクエストは、1つ目の引数として`heroesURL`を渡し、2つ目の引数としてコールバック関数名を渡します。 +レスポンスはコールバック関数でラップされます。そのコールバック関数は、JSONPメソッドによって返されたObservableを受け取って、パイプでエラーハンドラーに通します。 ### JSON以外のデータをリクエストする すべてのAPIがJSONデータを返すわけではありません。 -この次の例では、`DownloaderService`メソッドはサーバーからテキストファイルを読み込み、ファイル内容を記録します。`Observable`としてその内容を呼び出し元に返す前にです。 +この次の例では、`DownloaderService`のメソッドがサーバーからテキストファイルを読み取り、ファイルの内容をログに記録してから、それらの内容を` Observable`として呼び出し元に返します。 -`HttpClient.get()`は`responseType`オプションにより、デフォルトのJSONではなく文字列を返します。 +`HttpClient.get()`は`responseType`オプションがあるため、デフォルトのJSONではなく文字列を返します。 -RxJSの(「盗聴」のような)`tap`オペレーターにより、Obervableを通過する正常値とエラー値の双方を、コードがそれらを妨害することなく検査できます。 +RxJSの `tap` オペレーターにより、Obervableを通過する正常値とエラー値の双方を、コードがそれらを妨害することなく検査できます。 -`DownloaderComponent`の`download()`メソッドは、サービスのメソッドを購読することによってリクエストを開始します。 +`DownloaderComponent`の`download()`メソッドは、サービスのメソッドを購読することでリクエストを開始します。 -## エラーハンドリング +{@a error-handling} -サーバーでリクエストが失敗した場合、または貧弱なネットワーク接続が原因でサーバーに到達できない場合はどうなるでしょうか? `HttpClient`は成功したレスポンスの代わりに _エラー_ オブジェクトを返します。 +## リクエストエラーの処理 -`.subscribe()`に2番目のコールバックを追加することでコンポーネント内で処理 _できました_ +サーバーでリクエストが失敗した場合、`HttpClient`は成功したレスポンスの代わりに_error_オブジェクトを返します。 - - +サーバートランザクションを実行するのと同じサービスが、エラーの検査、解釈、および解決も実行する必要があります。 -データアクセスが失敗したときにユーザーに何らかのフィードバックを与えることは、確かによい考えです。 -しかし、`HttpClient`によって返された生のエラーオブジェクトを表示することは、最善の方法からほど遠いです。 +エラーが発生した場合、ユーザーに通知するために失敗した内容の詳細を取得できます。場合によっては、自動的に[リクエストの再試行](#retry)も可能です。 {@a error-details} -### エラーの詳細を得る +### エラーの詳細を取得する -エラーが発生したことを検出することが重要です。そのエラーを解釈し、ユーザーフレンドリーなレスポンスを構成することはもう少し複雑です。 +アプリケーションは、データアクセスが失敗したときに、ユーザーに役立つフィードバックを提供する必要があります。 +生のエラーオブジェクトは、フィードバックとして特に役立ちません。 +エラーが発生したことを検出することに加えて、エラーの詳細を取得し、それらの詳細を使用してユーザーフレンドリーなレスポンスを作成する必要があります。 -2種類のエラーが発生する可能性があります。サーバーバックエンドはリクエストを拒否し、HTTPレスポンスに404または500などのステータスコードを返します。 -これらはエラー_レスポンス_です。 +2種類のエラーが発生する可能性があります。 -あるいは、リクエストが正常に完了するのを妨げるネットワークエラーや、RxJSオペレーターでスローされた例外など、クライアント側で何かが間違っている可能性があります。 -これらのエラーは、JavaScriptの`ErrorEvent`オブジェクトを生成します。 +* サーバーバックエンドがリクエストを拒否し、404や500などのステータスコードでHTTPレスポンスを返す場合があります。これらはエラー_レスポンス_です。 -`HttpClient`は`HttpErrorResponse`で両方の種類のエラーを捕捉し、実際に何が起きたのかを調べるためにレスポンスを調べることができます。 +* 要求を正常に完了できないネットワークエラーや、RxJSオペレーター内でスローされた例外など、クライアント側で問題が発生する可能性があります。これらのエラーは`0`に設定された`status`と、`ProgressEvent`オブジェクトが含まれる`error`プロパティを持っています。`ProgressEvent`オブジェクトの`type`は詳細な情報を提供する可能性があります。 -エラー検査、解釈、および解決は、_コンポーネント_ではなく_サービス_で実行したいことです。 +`HttpClient`は、`HttpErrorResponse`で両方の種類のエラーをキャプチャします。そのレスポンスを調べて、エラーの原因を特定できます。 -このようなエラーハンドラーを最初に考案するかもしれません。 +次の例では、以前に定義された[ConfigService](#config-service "ConfigService defined")の中でエラーハンドラーを定義します。 - -このハンドラーは、RxJSの[`ErrorObservable`](#rxjs)を使いやすいエラーメッセージとともに返します。 -サービスの利用者は、サービスメソッドが何らかの`Observable`を、"悪い"ものであっても返すことを期待しています。 - - -今度は、`HttpClient`メソッドによって返された`Observables`を取得し、エラーハンドラーに_それらを渡します。_ +ハンドラーは、ユーザーフレンドリーなエラーメッセージとともにRxJS`ErrorObservable`を返します。 +次のコードでは、[パイプ](guide/pipes "Pipes guide")を使用し`HttpClient.get()`呼び出しによって返されたすべてのObservableをエラーハンドラーに送信するように、`getConfig()`メソッドが更新されています。 - - -### 再試行する +{@a retry} +### 失敗したリクエストの再試行 -場合によってはエラーが一時的で、再試行すると自動的に消えます。 -たとえば、ネットワークの中断はモバイルシナリオでは一般的であり、再試行すると成功する可能性があります。 +エラーは一時的なものであり、再試行すると自動的に消える場合があります。 +たとえば、ネットワークの中断はモバイルシナリオで一般的であり、再試行すると +成功する可能性があります。 +[RxJSライブラリ](guide/rx-library)はいくつかの_再試行_オペレーターを提供しています。 +たとえば、`retry()`オペレーターは、失敗した`Observable`を指定された回数だけ自動的に再サブスクライブします。`HttpClient`メソッド呼び出しの結果を_再サブスクライブ_すると、HTTPリクエストを再発行する効果があります。 -[RxJSライブラリ](#rxjs)には、価値のある_retry_オペレーターがいくつか用意されています。 -もっとも単純なものは`retry()`と呼ばれ、失敗した`Observable`に指定された回数だけ自動的に再購読します。`HttpClient`メソッド呼び出しの結果を_再購読_することは、HTTPリクエストを再発行するという効果があります。 +次の例は、失敗したリクエストをエラーハンドラーに渡す前に、`retry()`オペレーターにパイプする方法を示しています。 -それをエラーハンドラーの直前で`HttpClient`メソッドの結果に_パイプ_します。 - - -{@a rxjs} -## Observablesとオペレーター - -このガイドの前のセクションでは、RxJSの`Observables`と`catchError`や`retry`などのオペレーターについて説明しました。 -以降のセクションに進むと、もっと多くのRxJS由来のものに出会います。 - -[RxJS](http://reactivex.io/rxjs/)は、非同期およびコールバックベースのコードを_関数的かつリアクティブなスタイル_で作成するためのライブラリです。 -`HttpClient`を含む多くのAngular APIは、RxJSの`Observables`を生成し、利用します。 - - -RxJS自体はこのガイドの範囲外です。 あなたはウェブ上で多くの学習リソースを見つけるでしょう。 -最低限のRxJS知識でなんとかやっていくうちに、やがて`HttpClient`を効果的に使用するためにRxJSスキルを成長させたくなるでしょう。 - -これらのコードスニペットにしたがっている場合、そのスニペットに表示されるRxJSのObservableとオペレーターのシンボルをインポートする必要があることに注意してください。次の`ConfigService`のインポートは典型的なものです。 - - - -## HTTPヘッダー +## サーバーへのデータの送信 -多くのサーバーでは、保存操作に追加のヘッダーが必要です。 -たとえば、リクエストボディのMIMEタイプを明示的に宣言するために、「Content-Type」ヘッダーが必要な場合があります。あるいは、サーバーに承認トークンが必要なのかもしれません。 +サーバーからデータを取得することに加えて、`HttpClient`はPUT、POST、DELETEなどの他のHTTPメソッドをサポートしています。これらは遠隔のデータを変更するために使用できます。 -### ヘッダーを追加する {@a adding-headers} +このガイドのサンプルアプリケーションには、 +ヒーローを取得し、ユーザーがヒーローを追加、削除、更新できる「Tour of Heroes」の例の簡略版が含まれています。 +次のセクションでは、サンプルの`HeroesService`からのデータ更新メソッドの例を示します。 -`HeroesService`は、`HttpClient`のすべての保存メソッドに渡される`httpOptions`オブジェクトで、そのようなヘッダーを定義しています。 +### POSTリクエストの作成 - - - - -### ヘッダーを更新する {@a updating-headers} - -`HttpHeaders`クラスのインスタンスはイミュータブルなので、以前のオプションオブジェクト内の既存のヘッダーを直接変更することはできません。 - - -代わりに`set()`メソッドを使用してください。新しい変更が適用された現在のインスタンスのクローンを返します。 - -(以前のトークンが期限切れになった後に)次のリクエストを行う前に、承認ヘッダーを更新する方法は次のとおりです。 +多くの場合、アプリケーションはフォームを送信するときにPOSTリクエストを使用してサーバーにデータを送信します。 +次の例では、データベースにヒーローを追加するときに、`HeroesService`がHTTP POSTリクエストを実行します。 - - -## サーバーにデータを送る - -`HttpClient`は、サーバーからデータを取得するだけでなく、PUT、POST、DELETEなどの他のHTTPメソッドを使用してサーバーにデータを送信するという、変更リクエストをサポートします。 - -このガイドのサンプルアプリケーションには、ヒーローを取得してユーザーが追加、削除、および更新できるようにする、ツアー・オブ・ヒーローの簡略版が含まれています。 - - -次のセクションでは、サンプルのHeroesServiceメソッドの抜粋を示します。 - -### POSTリクエストを作る - -アプリケーションはしばしばサーバーにデータをPOSTします。 フォームを送信するときにPOSTします。 -次の例では、ヒーローをデータベースに追加するときに `HeroesService`がポストします。 - - -`HttpClient.post()`メソッドは、型パラメーター(サーバーが新しいヒーローを返すことを期待しています)を持っていてリソースURLを必要とする点で`get()`と似ています。 +`HttpClient.post()`メソッドは、型パラメータがあり、サーバーが特定の型のデータを返すことを期待するのを明示できるという点で、`get()`に似ています。このメソッドは、リソースURLと2つの追加パラメーターを取ります。 +* *body* - POSTするリクエストのボディ内のデータ +* *options* - メソッドオプションを含むオブジェクト。この場合のオプションは、[必要なヘッダーを指定してします](#adding-headers)。 +この例では、[前述](#error-details)のようにエラーを捕捉します。 -さらに2つのパラメーターを取ります。 +`HeroesComponent`がこのサービスのメソッドが返す`Observable`を購読することによって、 +実際のPOST処理が開始します。 -1. `hero` - リクエストのボディでPOSTするデータ -1. `httpOptions` - このケースでは[必要なヘッダーを定義する](#adding-headers)メソッドオプション - -もちろん、これは[前述](#error-details)とほぼ同じ方法でエラーを捕捉します。 - -`HeroesComponent`は、このサービスメソッドによって返された`Observable`を購読することによって、実際のPOST操作を開始します。 - - - -サーバーが新しくヒーローを追加することに成功してレスポンスすると、コンポーネントはそのヒーローを表示中の`heroes`リストに追加します。 - +サーバーが新しく追加されたヒーローを正常に返すと、 +コンポーネントはそのヒーローを画面に表示されている`heroes`リストに追加します。 -### DELETEリクエストを作る +### DELETEリクエストの作成 -このアプリケーションは、リクエストURLにヒーローのIDを渡すことによって、`HttpClient.delete`メソッドでヒーローを削除します。 +このアプリケーションは、リクエストURLにヒーローのIDを渡すことによって、 +`HttpClient.delete`メソッドを使用してヒーローを削除します。 - - -`HeroesComponent`は、このサービスメソッドによって返された`Observable`を購読することによって、実際のDELETEオペレーションを開始します。 - +`HeroesComponent`がこのサービスのメソッドが返す`Observable`を購読することによって、 +実際のDELETE処理が開始します。 - -コンポーネントは削除操作の結果を期待していないため、コールバックなしで購読します。結果を使用していなくても、依然として購読する必要があります。 `subscribe()`メソッドを呼び出すと、Observableが _実行_ されます。これは、DELETEリクエストを開始するものです。 +コンポーネントは削除処理の結果を要求していないため、コールバックなしで購読します。結果を使用していなくても、購読する必要があります。`subscribe()`メソッドを呼び出すと、Observableが_実行_され、DELETEリクエストが開始します。
-_subscribe()_ を呼ばなければ何も起こりません。 `HeroesService.deleteHero()`を呼び出すだけでは、**DELETEリクエストは開始されません。** +_subscribe()_を呼び出さなければ何も起こりません。`HeroesService.deleteHero()`を呼び出すだけでは、DELETEリクエストは開始されません。
- -{@a always-subscribe} -**常に_subscribe_を忘れないでください!** +### PUTリクエストの作成 -`HttpClient`メソッドは、そのメソッドから返されたObservableで`subscribe()`を呼び出すまでHTTPリクエストを開始しません。これは_すべての`HttpClient`メソッド_に当てはまります。 +アプリケーションは、HTTPクライアントサービスを使用してPUTリクエストを送信できます。 +次の`HeroesService`の例は、POSTの例と同様に、リソースを更新されたデータに置き換えます。 -
+ + -[`AsyncPipe`](api/common/AsyncPipe)なら自動的に購読したり購読を取り消しします。 +Observableを返すHTTPメソッドについていえば、呼び出し元の`HeroesComponent.update()`はリクエストを開始するため、`HttpClient.put()`から返されたObservableを[`subscribe()`する必要があります。](#always-subscribe "Why you must always subscribe.") -
+### ヘッダーの追加と更新 -`HttpClient`メソッドから返されたすべてのObservableは、意図的に_cold_です。 -HTTPリクエストは_遅延実行_され、実際に何かが起こる前に、`tap`や`catchError`のような追加の操作でObservableを拡張することができます。 +多くのサーバーでは、保存操作のために追加のヘッダーが必要です。 +たとえば、サーバーは認可トークンや、リクエスト本文のMIMEタイプを明示的に宣言するために「Content-Type」ヘッダーを必要とする場合があります。 +##### ヘッダーの追加 {@a adding-headers} -`subscribe(...)`を呼び出すと、Observableの実行がトリガーされ、`HttpClient`がHTTPリクエストを作成してサーバーに送信します。 +`HeroesService`は、`HttpClient`の保存メソッドすべてに渡される`httpOptions`オブジェクトで、 +そのようなヘッダーを定義しています。 + + -これらのObservableは実際のHTTPリクエストの_設計図_と考えることができます。 +##### ヘッダーの更新 -
+`HttpHeaders`クラスのインスタンスはイミュータブルなので、 +前述のoptionsオブジェクト内の既存のヘッダーを直接変更することはできません。 +代わりに`set()`メソッドを使用して、新しい変更が適用された現在のインスタンスのクローンを返します。 -実際、個々の`subscribe()`はObservableを分離して独立した実行を開始します。 -2回の購読は2つのHTTPリクエストを引き起こします。 +次の例は、古いトークンの有効期限が切れたときに、次のリクエストを行う前に認可ヘッダーを更新する方法を示しています。 -```javascript -const req = http.get('/api/heroes'); -// .subscribe()が呼ばれていないため、まだ0リクエストです。 -req.subscribe(); -// 1つ目のリクエストが作られます。 -req.subscribe(); -// 2つ目のリクエストが作られます。 -``` -
+ + + +{@a url-params} -### PUTリクエストを作る +## HTTP URLパラメーターの設定 -アプリケーションはリソースを更新されたデータで完全に置き換えるためにPUTリクエストを送信します。 -次の`HeroesService`の例はPOSTの例と似ています。 +URLクエリ文字列を`HttpRequest`に追加するには、`params`リクエストオプションに`HttpParams`クラスを使用します。 - +import {HttpParams} from "@angular/common/http"; + + + + region="searchHeroes" linenums="false"> -[上記で説明](#always-subscribe)した理由で、呼び出し元(この場合は`HeroesComponent.update()`)は、リクエストを開始するために`HttpClient.put()`から返されたObservableを`subscribe()`する必要があります。 +検索語がある場合、コードはHTML URLエンコードされた検索パラメーターをもつoptionsオブジェクトを作成します。 +たとえば検索語が「cat」の場合、GETリクエストのURLは`api/heroes?name=cat`になります。 +`HttpParams`オブジェクトはイミュータブルです。optionsを更新する必要がある場合、`.set()`メソッドの戻り値を保存してください。 -## 高度な使い方 +`fromString`変数を使用して、クエリ文字列から直接HTTPパラメータを作成することもできます。 -私たちは、`@angular/common/http`の基本的なHTTP機能について議論しましたが、単純な要求をしてデータを戻す以上のことを行う必要があることもあります。 + +const params = new HttpParams({fromString: 'name=foo'}); + -{@a intercepting-requests-and-responses } -### HTTPインターセプター -_HTTPのインターセプト_は`@angular/common/http`の主要な機能です。 -インターセプトのために、アプリケーションからサーバーへのHTTPリクエストを検査および変換する_インターセプター_を宣言します。 -また、同じインターセプターは、アプリケーションの途中でサーバーのレスポンスを検査して変換することもできます。 -複数のインターセプターは、リクエスト/レスポンスハンドラーの_前後の_チェインを形成します。 +{@a intercepting-requests-and-responses} +## リクエストとレスポンスのインターセプト -インターセプターは、すべてのHTTPリクエスト/レスポンスに対して、認証からロギングまで、さまざまな_暗黙_のタスクを一まとまりの標準的な方法で実行できます。 +インターセプトのために、アプリケーションからサーバーへのHTTPリクエストを検査して変換する_インターセプター_を宣言します。 +同じインターセプターが、アプリケーションに返ってくるサーバーのレスポンスを検査および変換することもできます。 +複数のインターセプターが、リクエスト/レスポンスハンドラーの_前後の_チェーンを形成します。 -インターセプト無しでは、開発者は各`HttpClient`メソッド呼び出しに対してこれらのタスクを_明示的_に行う必要があります。 +インターセプターは、すべてのHTTPリクエスト/レスポンスに対して、認証からロギングまで、さまざまな_暗黙の_タスクを型どおりの、標準的な方法で実行できます。 +インターセプト無しでは、開発者は +各`HttpClient`メソッド呼び出しに対してこれらのタスクを_明示的に_実装する必要があります。 -#### インターセプターを書く +### インターセプターを書く インターセプターを実装するには、`HttpInterceptor`インターフェースの`intercept()`メソッドを実装するクラスを宣言します。 -ここに、何も触れずにリクエストを単に渡すだけの_noop_インターセプターがあります。 - -`intercept`メソッドは、リクエストを最終的にHTTPレスポンスを含む`Observable`に変換します。 -この意味で、各インターセプターは完全に単独でリクエストを処理することができます。 +`intercept`メソッドは、リクエストを最終的にHTTPレスポンスを返す`Observable`に変換します。 +こういう意味では、各インターセプターは完全に単独でリクエストを処理することができます。 -ほとんどのインターセプターは、リクエストを検査し、[`HttpHandler`](api/common/http/HttpHandler)インターフェースを実装している`next`オブジェクトの`handle()`メソッドへ(おそらく変更された)リクエストを転送します。 +ほとんどのインターセプターは、途中でリクエストを検査し、[`HttpHandler`](api/common/http/HttpHandler)インターフェースを実装する`next`オブジェクトの`handle()`メソッドに変更された可能性のあるリクエストを転送します。 ```javascript export abstract class HttpHandler { @@ -500,54 +587,54 @@ export abstract class HttpHandler { } ``` -`intercept()`と同様に、`handle()`メソッドは、HTTPリクエストを最終的にサーバーのレスポンスを含む[`HttpEvents`](#httpevents)の`Observable`に変換します。`intercept()`メソッドは、そのObservableを検査し、それを呼び出し側に返す前に変更することができます。 +`intercept()`と同様に、`handle()`メソッドは、HTTPリクエストを最終的にサーバーのレスポンスを含む[`HttpEvents`](#interceptor-events)の`Observable`に変換します。`intercept()`メソッドは、そのObservableを検査し、呼び出し元に返す前に変更することができます。 -この_何もしない_インターセプターは、単に元のリクエストとともに`next.handle()`を呼び出し、何もせずにObservableを返します。 +この_何もしない_インターセプターは、元のリクエストを渡して`next.handle()`を呼び出し、何もせずにObservableを返します。 -#### _next_オブジェクト +### _next_オブジェクト `next`オブジェクトは、インターセプターのチェーン内の次のインターセプターを表します。 チェーンの最後の`next`は、リクエストをサーバーに送信し、サーバーのレスポンスを受け取る`HttpClient`バックエンドハンドラーです。 ほとんどのインターセプターは、`next.handle()`を呼び出して、リクエストが次のインターセプター、そして最終的にはバックエンドハンドラーに流れるようにします。 -インターセプターは、`next.handle()`をスキップしチェーンを近道して、人工のサーバーレスポンスで[自身の`Observable`を返す](#caching)こともできます。 +インターセプターは、`next.handle()`の呼び出しをスキップしチェーンを近道して、人工のサーバーレスポンスで[自身の`Observable`を返す](#caching)こともできます。 これは、Express.jsなどのフレームワークでよく見られるミドルウェアパターンです。 -#### インターセプターを提供する +### インターセプターを提供する `NoopInterceptor`は、Angularの[依存性の注入(DI)](guide/dependency-injection)システムによって管理されるサービスです。 他のサービスと同様に、アプリケーションが使用する前にインターセプタークラスを提供する必要があります。 -インターセプターは`HttpClient`サービスの(オプショナルな)依存関係であるため、 -`HttpClient`を提供する同じインジェクター(またはインジェクターの親)にそれらを提供する必要があります。 +インターセプターは`HttpClient`サービスの依存オブジェクトであるため、 +`HttpClient`を提供しているのと同じインジェクター、または親インジェクターにそれらを提供する必要があります。 DIが`HttpClient`を作成した_後に_提供されるインターセプターは無視されます。 -このアプリケーションは、`AppModule`で`HttpClientModule`をインポートする副作用として、アプリケーションのルートインジェクターに`HttpClient`を提供します。 +このアプリケーションは、`AppModule`で`HttpClientModule`をインポートする副作用として、アプリケーションのルートインジェクターに`HttpClient`を提供しています。 同様にインターセプターは`AppModule`の中で提供すべきです。 `@angular/common/http`から`HTTP_INTERCEPTORS`インジェクショントークンをインポートした後、 次のように`NoopInterceptor`プロバイダーを記述します。 - `multi:true`オプションに注意してください。 -この必須設定は、Angularに`HTTP_INTERCEPTORS`は単一の値ではなく値の配列を注入する_マルチプロバイダー_のトークンであることを伝えます。 +この必須設定は、Angularに`HTTP_INTERCEPTORS`は +単一の値ではなく値の配列を注入する_マルチプロバイダー_のトークンであることを伝えます。 - -このプロバイダーを`AppModule`のプロバイダー配列に直接追加することができますが、 -それはむしろ冗長であり、 +このプロバイダーを `AppModule`のproviders配列に直接追加することができます。 +ただし、それはむしろ冗長であり、 より多くのインターセプターを作成し、同じ方法でそれらを提供するよい方法があります。 -これらのインターセプターを提供する[順序に細心の注意](#インターセプターの順番)を払う必要があります。 - +また、これらのインターセプターを提供する +[順序に細心の注意](#interceptor-order)を払う必要があります。 -最初のインターセプターである`NoopInterceptor`から始まる`httpInterceptorProviders`配列の中にすべてのインターセプタープロバイダーを集める「バレル」ファイルを作成することを検討してください。 +この最初の`NoopInterceptor`から始まる`httpInterceptorProviders`配列の中にすべてのインターセプタープロバイダーを集める「バレル」ファイルを作成することを検討してください。 - @@ -555,14 +642,14 @@ DIが`HttpClient`を作成した_後に_提供されるインターセプター 次に、それをインポートして`AppModule`の _providers配列_ に追加します。 - -新しいインターセプターを作成するとき、それらを`httpInterceptorProviders`配列に追加するだけです。`AppModule`を開く必要はありません。 - +新しいインターセプターを作成するとき、それらを`httpInterceptorProviders`配列に追加するだけです。 +`AppModule`を開く必要はありません。
@@ -570,270 +657,338 @@ DIが`HttpClient`を作成した_後に_提供されるインターセプター
-#### インターセプターの順番 +### インターセプターの順番 {@a interceptor-order} Angularは、あなたが提供した順序でインターセプターを適用します。 -インターセプター_A_、_B_、_C_を提供すると、リクエストは_A-> B-> C_で流れ、レスポンスは_C-> B-> A_で流れます。 +たとえば、サーバーに送信する前にHTTPリクエストの認証を処理し、ログに記録する必要がある状況を考えてみます。 このタスクを実行するには、`AuthInterceptor`サービスを提供してから、`LoggingInterceptor`サービスを提供します。 +送信リクエストは`AuthInterceptor`から`LoggingInterceptor`に流れます。 +これらのリクエストからのレスポンスは、`LoggingInterceptor`から`AuthInterceptor`へと逆方向に流れます。 +以下は、プロセスを視覚的に表したものです。 + -後でインターセプターを変更したり、インターセプターを削除したりすることはできません。 -インターセプターを動的に有効または無効にする必要がある場合は、その機能をインターセプター自体に組み込む必要があります。 +
-#### _HttpEvents_ + プロセスの最後のインターセプターは常に、サーバーとの通信を処理する`HttpBackend`です。 -ほとんどの`HttpClient`メソッドが行うように、`intercept()`と`handle()`メソッドは`HttpResponse`のObservableを返すと思っていたかもしれません。 +
-代わりに`HttpEvent`のObservableを返します。 +後で順序を変更したり、インターセプターを削除したりすることはできません。 +インターセプターを動的に有効または無効にする必要がある場合は、その機能をインターセプター自体に組み込む必要があります。 -これは、インターセプターがそれらの`HttpClient`のメソッドよりも低いレベルで動作するためです。ひとつのHTTPリクエストでは、アップロードおよびダウンロードの進行状況イベントを含む複数の_イベント_を生成できます。`HttpResponse`クラス自体は実際にはイベントで、その型は`HttpEventType.Response`です。 +{@a interceptor-events} -多くのインターセプターは外に出ていくリクエストのみに関心があり、単に`next.handle()`からイベントストリームを変更せずに返します。 +### インターセプターイベントの処理 -しかし、`next.handle()`からのレスポンスを調べて変更するインターセプターは、これらすべてのイベントを見て確かめます。 -インターセプターは、_やむを得ない理由_がない限り、_すべてのイベントをそのまま_返す必要があります。 +ほとんどの`HttpClient`メソッドは`HttpResponse`のObservableを返します。 +`HttpResponse`クラス自体は実際にはイベントであり、その型は`HttpEventType.Response`です。 +ただし、単一のHTTPリクエストで、アップロードおよびダウンロードの進行状況イベントなど、他の型の複数のイベントが発生する可能性があります。 +`HttpInterceptor.intercept()`や`HttpHandler.handle()`は`HttpEvent`のObservableを返します。 +多くのインターセプターは、送信リクエストのみに関係し、リクエストを変更せずに `next.handle()`からイベントストリームを返します。 +ただし、一部のインターセプターは、`next.handle()`からのレスポンスを検査して変更する必要があります。これらの操作は、ストリーム内のこれらのイベントのすべてを確認できます。 -#### イミュータビリティ(不変性) {@a immutability} +{@a immutability} -インターセプターはリクエストとレスポンスを変更することができますが、`HttpRequest`と`HttpResponse`のインスタンスのプロパティは`readonly`で、それらをほぼ不変にします。 +インターセプターはリクエストとレスポンスを変更できますが、 +`HttpRequest`と`HttpResponse`インスタンスのプロパティは`readonly`であり、 +ほとんどイミュータブルになります。 +これらは正当な理由でイミュータブルです。アプリケーションはリクエストが成功する前に数回再試行する場合がある、すなわち、インターセプターチェーンが同じリクエストを複数回再処理する可能性があるためです。 +インターセプターが元のリクエストオブジェクトを変更できる場合、再試行された操作は、元のリクエストではなく、変更されたリクエストから開始します。イミュータビリティは、インターセプターが試行ごとに同じ要求を確認することを保証します。 +
+ インターセプターは、やむを得ない理由がない限り、すべてのイベントを変更せず返す必要があります。 -それらは正当な理由からイミュータブルです。アプリケーションは、成功する前にリクエストを何度か再試行することがあります。つまり、インターセプターのチェーンが同じリクエストを複数回再処理する可能性があります。 -インターセプターが元のリクエストオブジェクトを変更できる場合、再試行された操作は元のものではなく変更されたリクエストから開始されます。不変性は、インターセプターが各試行に対して同じリクエストを見ることを保証します。 +
-TypeScriptは、`HttpRequest`の読み取り専用プロパティにセットできないようにします。 +TypeScriptが、`HttpRequest`の読み取り専用プロパティを設定できないようにしています。 ```javascript - // req.urlが読み取り専用であるため、Typescriptは次の割り当てを許可しません + // req.urlがreadonlyであるため、Typescriptは次の代入を許可しない req.url = req.url.replace('http://', 'https://'); ``` -リクエストを変更するには、最初にクローンを作成し、クローンを変更してから`next.handle()`に渡します。 -この例のように、ひとつの手順でリクエストを複製して変更することができます。 - -`clone()`メソッドのハッシュ引数は、他のものをコピーしながらリクエストの特定のプロパティを変更することを可能にします。 +`clone()`メソッドのハッシュ引数を使用すると、リクエストの特定のプロパティを変更しながら、他のプロパティをコピーできます。 -##### リクエストボディ +#### リクエストボディの変更 -`readonly`代入ガードは、プロパティの深い更新を防ぐことはできません。 -特に、リクエストボディオブジェクトのプロパティを変更できないようにすることはできません。 +`readonly`の代入ガードは、深い更新を防ぐことはできません。特に、 +リクエストボディオブジェクトのプロパティを変更することを防ぐことはできません。 ```javascript - req.body.name = req.body.name.trim(); // bad idea! + req.body.name = req.body.name.trim(); // 良くないアイディア! ``` -リクエストボディを変更する必要がある場合は、次の例のように、最初にコピーし、コピーを変更し、リクエストを`clone()`して、クローンのボディを新しいボディで設定します。 +リクエストボディを変更する必要がある場合は、次の手順にしたがってください。 +1. ボディをコピーして、コピーに変更を加えます。 +2. `clone()`メソッドを使用して、リクエストオブジェクトのクローンを作成します。 +3. クローンのボディを変更されたコピーに置き換えます。 - -##### リクエストボディを消去する +#### クローンのリクエストボディを消去する + +リクエストボディを置き換えるのではなく、消去する必要がある場合があります。 +これを行うには、複製されたリクエストボディを `null`に設定します。 -場合によっては、リクエストボディを置き換えるのではなく消去する必要があります。 -クローンされたリクエストボディを`undefined`に設定した場合、Angularはボディをそのまま保持しようとしていると推論します。 -これはあなたが望むものではありません。 -クローンされたリクエストボディを`null`に設定すると、Angularはリクエストボディをクリアしようとしていることを知ります。 +
+ +**Tip**: 複製されたリクエストボディを`undefined`に設定すると、Angularはボディをそのままにしておくつもりであると想定します。 + +
```javascript - newReq = req.clone({ ... }); // ボディは言及しない=>元のボディを保持する - newReq = req.clone({ body: undefined }); // 元のボディを保持する + newReq = req.clone({ ... }); // ボディは記載されていない => 元々のボディを保持する + newReq = req.clone({ body: undefined }); // 元々のボディを保持する newReq = req.clone({ body: null }); // ボディを消去する ``` -#### デフォルトのヘッダーをセットする +## Httpインターセプターのユースケース + +以下は、インターセプターのよくある使用法です。 -アプリケーションでは、インターセプターを使用して外に出ていくリクエストにデフォルトのヘッダーを設定することがよくあります。 +### デフォルトのヘッダーをセットする -サンプルアプリケーションには、承認トークンを生成する`AuthService`があります。 -トークンを取得するためにそのサービスを注入する`AuthInterceptor`があり、そのトークンをもつ承認ヘッダーをすべての外部リクエストに追加します。 +アプリケーションでは、インターセプターを使用して外部へのリクエストにデフォルトのヘッダーを設定することがよくあります。 +サンプルアプリケーションには、認可トークンを生成する`AuthService`があります。 +これは、トークンを取得するサービスを注入し、 +トークンをすべての外部へのリクエストの認可ヘッダーに追加する、`AuthInterceptor`です。 - -新しいヘッダーを設定するリクエストを複製する方法は非常に一般的です。そのために`setHeaders`ショートカットがあります。 +新しいヘッダーを設定するため、リクエストのクローンを作成するというプラクティスは非常によくあるため、 +`setHeaders`ショートカットがあります。 - - ヘッダーを変更するインターセプターは、次のようなさまざまな操作に使用できます。 -* 認証/承認 -* キャッシュ動作 たとえば、`If-Modified-Since` -* XSRFプロテクション - -#### ロギング +* 認証/認可 +* キャッシュ動作。たとえば、`If-Modified-Since` +* XSRF保護 -インターセプターはリクエストとレスポンスを_一緒に_処理できるため、HTTP操作全体について時間の計測やログの記録ができます。 +### リクエストとレスポンスのペアをロギングする +インターセプターはリクエストとレスポンスを_一緒に_処理できるため、HTTPオペレーション全体について時間の計測やログの記録ができます。 次の`LoggingInterceptor`を考えてみましょう。 -これは、リクエストの時間とレスポンスの時間を取得し、注入された`MessageService`で経過時間とともに結果を記録します。 +これは、リクエストの時間とレスポンスの時間を取得し、 +注入された`MessageService`で経過時間とともに結果を記録します。 - - -RxJSの`tap`オペレーターは、リクエストが成功するか失敗したかを取得します。 -RxJSの`finalize`オペレーターは、レスポンスのObservableがエラーか(必ず起きる)完了のいずれかを返したときに呼ばれ、その結果を`MessageService`に報告します。 +RxJSの`tap`オペレーターは、リクエストが成功したか失敗したかを取得します。 +RxJSの`finalize`オペレーターは、レスポンスのObservableがエラーとなったか、完了したときに呼ばれ、その結果を`MessageService`に報告します。 +`tap`も`finalize`も、呼び出し元に返されるObservableのストリームの値には影響を及ぼしません。 -`tap`も`finalize`も、呼び出し元に返されたObservableのストリームの値には触れません。 +{@a custom-json-parser} -#### キャッシング {@a caching} +### カスタムJSONパース処理 -インターセプターは`next.handle()`に転送せずに、リクエストを自身で処理できます。 +インターセプターを使用して、組み込みのJSONパース処理をカスタム実装に置き換えることができます。 -たとえば、特定のリクエストとレスポンスをキャッシュして、パフォーマンスを向上させることができます。 -既存のデータサービスを妨げることなく、インターセプターにキャッシュを委任できます。 +次の例の`CustomJsonInterceptor`は、これを実現する方法を示しています。 +インターセプトされたリクエストが`'json'`レスポンスを期待している場合、組み込みのJSONパース処理を無効化するため、`responseType`は`'text'`に変更されます。 +次に、注入された`JsonParser`を介してレスポンスがパースされます。 -`CachingInterceptor`はこのアプローチを示しています。 + + - +独自のカスタム`JsonParser`を実装できます。 +これは、特別なdate reviverをもつカスタムJsonParserです。 + + -`isCachable()`関数はリクエストがキャッシュ可能かどうかを決定します。 -このサンプルでは、npmパッケージの検索APIに対するGETリクエストのみがキャッシュ可能です。 +`CustomJsonInterceptor`とともに、`CustomParser`を提供します。 -リクエストがキャッシュ可能でない場合、インターセプターはリクエストをチェーン内の次のハンドラーに転送します。 + + -キャッシング可能なリクエストがキャッシュ内に見つかった場合、インターセプターはキャッシュされたレスポンスをもつ`of()`の_Observable_を返し、`next`ハンドラー(および他のすべての下流のインターセプター)をバイパスします。 +{@a caching} +### リクエストをキャッシュする +インターセプターは`next.handle()`に転送せずに、自分でリクエストを処理できます。 -キャッシュ可能なリクエストがキャッシュにない場合、コードは`sendRequest`を呼び出します。 +たとえば、パフォーマンスを向上させるために、特定のリクエストとレスポンスをキャッシュすると決めることがあるかもしれません。 +既存のデータサービスを妨げることなく、インターセプターにキャッシュを移譲できます。 -{@a send-request} - + region="v1" + header="app/http-interceptors/caching-interceptor.ts)"> -`sendRequest`関数は、npm apiが禁止しているため、ヘッダーのない[リクエストのクローン](#immutability)を作成します。 - +* `isCachable()`関数はリクエストがキャッシュ可能かどうかを決定します。 +このサンプルでは、npmパッケージの検索APIに対するGETリクエストのみがキャッシュ可能です。 -そのリクエストを`next.handle()`に転送します。これは最終的にサーバーを呼び出し、サーバーのレスポンスを返します。 +* リクエストがキャッシュ可能でない場合、インターセプターはリクエストを +チェーン内の次のハンドラーに転送します。 +* キャッシング可能なリクエストがキャッシュ内に見つかった場合、インターセプターは +キャッシュされたレスポンスを`of()`_Observable_で返し、`next`ハンドラーおよび他のすべての下流のインターセプターをバイパスします。 -`sendRequest`がアプリケーションに戻る途中で_レスポンスをインターセプトする_方法に注意してください。 -`tap()`オペレーターによりレスポンスを_パイプ_して、そのコールバックでレスポンスをキャッシュに追加します。 +* キャッシュ可能なリクエストがキャッシュにない場合、コードは`sendRequest()`を呼び出します。 +この関数はリクエストのクローンを`next.handle()`に転送し、最終的にサーバーを呼び出してサーバーのレスポンスを返します。 +{@a send-request} + + -元のレスポンスは、インターセプターのチェーンを通ってアプリケーション呼び出し元にオリジナルの状態で戻ります。 - +
-`PackageSearchService`のようなデータサービスは、`HttpClient`リクエストのいくつかは実際にはキャッシュされたレスポンスを返すものがあることに気づいていません。 +`sendRequest()`がアプリケーションに返ってくる途中の_レスポンスをインターセプトする_方法に注意してください。 +`tap()`オペレーターによりレスポンスを_パイプ_して、そのコールバックでレスポンスをキャッシュに追加します。 +元のレスポンスは、インターセプターのチェーンを通って +アプリケーション呼び出し元にオリジナルの状態で戻ります。 -{@a cache-refresh} -#### 複数の値を返す_Observable_ +`PackageSearchService`のようなデータサービスは、 +`HttpClient`リクエストのいくつかは実際にはキャッシュされたレスポンスを返すものがあることを知りません。 -`HttpClient.get()`メソッドは、通常、データまたはエラーを発行する_Observable_を返します。 -一部の人々は、それを "_1回だけで終わりの_"Observableと表現しています。 +
+ -しかし、インターセプターはこれを1回以上発行する_Observable_に変更することができます。 +### インターセプターを使用して複数の値を要求する -改訂されたバージョンの`CachingInterceptor`は、キャッシュされたレスポンスを直ちに発行する_Observable_をオプションで返します。 -これは、リクエストをNPM web APIにまずは送信し、あとで、更新された検索結果で再度発行します。 +`HttpClient.get()`メソッドは通常、データまたはエラーのいずれかの単一の値を発行するObservableを返します。 +インターセプターはこれを、[複数の値](guide/observables)を発行するObservableに変更できます。 +次の修正された`CachingInterceptor`は、任意でObservableを返します。 +このObservableは、キャッシュされたレスポンスをすぐに発行し、リクエストをパッケージ検索APIに送信し、 +後で最新の検索結果を再度発行します。 - -_cache-then-refresh_オプションは、**カスタム `x-refresh`ヘッダー**の存在によってトリガーされます。 -
-`PackageSearchComponent`のチェックボックスは、 -`PackageSearchService.search()`の引数の1つである`withRefresh`フラグをトグルします。 -その`search()`メソッドは、`HttpClient.get()`を呼び出す前にカスタム`x-refresh`ヘッダを作成し、それをリクエストに追加します。 +_cache-then-refresh_オプションは、カスタムの`x-refresh`ヘッダーが存在するとトリガーされます。 +`PackageSearchComponent`のチェックボックスは、`withRefresh`フラグを切り替えます。 +これは`PackageSearchService.search()`の引数の1つです。 +`search()`メソッドはカスタムの`x-refresh`ヘッダーを作成し、 +`HttpClient.get()`を呼び出す前にそれをリクエストに追加します。
-改訂された`CachingInterceptor`は、 -[上記](#send-request)の`sendRequest()`メソッドを使用して、 -キャッシュされた値があるかどうかにかかわらずサーバーリクエストを準備します。 -`results$`のObservableは購読したときにリクエストを行います。 +修正された`CachingInterceptor`は、[上記](#send-request)で説明したのと同じ`sendRequest()`メソッドを使用して、 +キャッシュされた値があるかどうかに関係なく、 +サーバーリクエストを設定します。 +`results$`Observableは、サブスクライブ時にリクエストを行います。 -キャッシュされた値がない場合、インターセプターは`results$`を返します。 +* キャッシュされた値がない場合、インターセプターは`results$`を返します。 +* If there is a cached value, the code *pipes* the cached response onto `results$`. This produces a recomposed observable that emits two responses, so subscribers will see a sequence of these two responses: + * The cached response that's emitted immediately + * The response from the server, that's emitted later -キャッシュされた値がある場合、コードはキャッシュされたレスポンスを`results$`にパイプし、 -2回発行する再構成されたObservableを生成します。 -最初に(そして直ちに)キャッシュされたレスポンスを、 -その後サーバーからのレスポンスが続きます。 -サブスクライバーは_2つ_のレスポンスのシーケンスを参照します。 +{@a report-progress} -### リクエストの設定 +## リクエストの進行状況の追跡と表示 -外部へのリクエストの他の設定は、`HttpClient`メソッドの最後の引数として渡されたオプションオブジェクトを介して行えます。 +アプリケーションが大量のデータを転送し、それらの転送に長い時間がかかる場合があります。 +ファイルのアップロードは典型的な例です。 +そのような転送の進行状況に関するフィードバックを提供することにより、ユーザーによりよい体験を提供します。 +プログレスイベントを有効にしてリクエストを行うには、 +`reportProgress`オプションをtrueに設定して`HttpRequest`のインスタンスを作成し、プログレスイベントを追跡できるようにします。 -[ヘッダーを追加する](#adding-headers)では、 -`HeroesService`がオプションオブジェクト(`httpOptions`)をその保存メソッドに渡すことでデフォルトヘッダーを設定していました。 -もっと他のこともできます。 + + -#### URLクエリ文字列 +
-このセクションでは、`HttpParams`クラスを使ってURLクエリ文字列を`HttpRequest`に加える方法を見ていきます。 +**Tip**: すべてのプログレスイベントは変更検知をトリガーします。したがって、UIで進捗状況を本当に報告する必要がある場合にのみ、それらを有効にしてください。 -次の`searchHeroes`メソッドは名前に検索語を含むヒーローをクエリします。 -`HttpParams`クラスのインポートから始めます。 +[`HttpClient.request()`](api/common/http/HttpClient#request)でHTTPメソッドを使うときには、 +[`observe: 'events'`](api/common/http/HttpClient#request)で転送の進行を含むすべてのイベントを見るように設定してください。 - -import {HttpParams} from "@angular/common/http"; - +
+ +次に、このリクエストオブジェクトを`HttpClient.request()`メソッドに渡します。 +このメソッドは、[インターセプター](#interceptor-events)によって処理されたのと同じイベントである`HttpEvents`の`Observable`を返します。 + path="http/src/app/uploader/uploader.service.ts" + region="upload-body" + header="app/uploader/uploader.service.ts (upload body)"> -検索語がある場合、コードは、HTML URLエンコードされた検索パラメーターをもつオプションオブジェクトを作成します。 -その語句が「foo」の場合、GETリクエストURLは`api/heroes/?name=foo`になります。 - -`HttpParams`はイミュータブルなので、オプションを更新するためには、その`.set()`メソッドの戻り値を確保する必要があります。 +`getEventMessage`メソッドは、イベントストリーム中の各タイプの`HttpEvent`を解釈します。 -#### `fromString`を使ってHttpParamsを作成 + + -`fromString`変数を使って、クエリ文字から直接にHTTPパラメーターを作成することもできます。 +
- -const params = new HttpParams({fromString: 'name=foo'}); - +このガイドのサンプルアプリケーションには、アップロードされたファイルを受け入れるサーバーがありません。 +`app/http-interceptors/upload-interceptor.ts`の`UploadInterceptor`は、 +アップロードリクエストをインターセプトしてショートサーキットし、 +シミュレートされたイベントのObservableを返します。 -### リクエストのデバウンス +
-このサンプルには_npmパッケージの検索_機能が含まれています。 +## デバウンスによるサーバーとのやりとりの最適化 -ユーザーが検索ボックスに名前を入力すると、 -「PackageSearchComponent」は、その名前をもつパッケージの検索リクエストをNPMのウェブAPIに送信します。 +ユーザー入力に応じてHTTPリクエストを行う必要がある場合、キーストロークごとにリクエストを送信するのは効率的ではありません。 +ユーザーが入力をやめるのを待ってからリクエストを送信する方がよいでしょう。 +この手法はデバウンスとして知られています。 -ここにテンプレートからの関連する抜粋があります。 +次のテンプレートについて考えてみます。このテンプレートでは、ユーザーが検索語を入力して、名前からパッケージを見つけることができます。 +ユーザーが検索ボックスに名前を入力すると、`PackageSearchComponent`は +その名前のパッケージの検索リクエストをパッケージ検索APIに送信します。 -`(keyup)`イベントバインディングはすべてのキーストロークをコンポーネントの`search()`メソッドに送ります。 +ここでは、`keyup`イベントバインディングは、すべてのキーストロークをコンポーネントの`search()`メソッドに送信します。 -すべてのキーストロークに対してリクエストを送信することは高いコストになる可能性があります。 -ユーザーが入力をやめるのを待ってからリクエストを送信する方がよいでしょう。 -この抜粋に示すように、RxJSオペレーターで実装すれば簡単です。 +
+ +`$event.target`の型は、テンプレート内の`EventTarget`に過ぎません。 +`getValue()`メソッドでは、ターゲットが`HTMLInputElement`にキャストされ、その`value`プロパティへの型安全なアクセスが可能になります。 + + + +
+ +次のスニペットは、RxJSオペレーターを使用してこの入力のデバウンスを実装します。 `searchText$`は、ユーザーからの検索ボックス値のシーケンスです。 -RxJSの`Subject`として定義されていて、マルチキャストする`Observable`であることを意味します。 -これは、`search()`メソッドにあるように、 -`next(value)`を呼び出すことによって自身のための値を発行できます。 +これは、RxJSの`Subject`として定義されています。 +`Subject`は、`search()`メソッドで行っているように、`next(value)`を呼び出すことによって、 +自身に対して値を発行できるマルチキャスト`Observable`です。 -注入された`PackageSearchService`にすべての`searchText`値を直接転送するのではなく、 -`ngOnInit()`のコードは3つのオペレーターを使って検索値を_パイプ_します。 +すべての`searchText`値を注入された`PackageSearchService`に直接転送するのではなく、 +`ngOnInit()`のコードは、検索値を3つのオペレーターにパイプしています。これにより、検索値が新しい値でかつユーザーが入力を停止した場合にのみ、検索値がサービスに到達します。 -1. `debounceTime(500)` - ユーザーが入力を停止するのを待ちます(この場合は1/2秒)。 +* `debounceTime(500)`⁠—ユーザーが入力を停止するのを待ちます(この場合は1/2秒)。 -1. `distinctUntilChanged()` - 検索テキストが変わるまで待ちます。 +* `distinctUntilChanged()`⁠—検索テキストが変わるまで待ちます。 -1. `switchMap()` - 検索リクエストをサービスに送ります。 +* `switchMap()`⁠—検索リクエストをサービスに送信します。 -このコードは、`packages$`をこの再構成された検索結果の`Observable`に設定します。 -テンプレートは[AsyncPipe](api/common/AsyncPipe)を使用して`packages$`を購読し、 -値が来たら検索結果を表示します。 - -検索値がサービスに到達するのは、それが新しい値でユーザーが入力を停止した場合のみです。 +このコードは、この再構成された検索結果の`Observable`に`packages$`を設定します。 +テンプレートは、[AsyncPipe](api/common/AsyncPipe)を使用して`packages$`をサブスクライブし、 +検索結果が届いた際に表示します。
-`withRefresh`オプションについては[後述](#cache-refresh)します。 +`withRefresh`オプションの詳細については、[インターセプターを使用して複数の値を要求する](#cache-refresh)を参照してください。
-#### _switchMap()_ - -`switchMap()`オペレーターには3つの重要な特徴があります。 +### *switchMap()*オペレーターの使用 -1. `Observable`を返す関数の引数をとります。 -`PackageSearchService.search`は他のデータサービスメソッドと同様に`Observable`を返します。 +The `switchMap()`オペレーターは、`Observable`を返す関数を引数に取ります。 +たとえば、`PackageSearchService.search`は他のデータサービスメソッドと同様に`Observable`を返します。 +以前の検索リクエストがまだ実行中である場合(接続が悪い場合など)、 +オペレーターはリクエストをキャンセルして新しいリクエストを送信します。 -2. 以前の検索リクエストがまだ_実行中である場合_(接続が悪い場合など)、 -そのリクエストをキャンセルして新しいリクエストを送信します。 +サービスのレスポンスをサーバーが順不同で返したとしても、 +`switchMap()`は、元のリクエストの順序で返すことに注意してください。 -3. サーバーがそれらを順不同で戻しても、 -サービスのレスポンスは元のリクエストの順序で戻されます。
このデバウンスロジックを再利用しようと考えるなら、 -ユーティリティ関数または`PackageSearchService`自体に移すことを検討してください。 +ユーティリティ関数または `PackageSearchService`自体に移動することを検討してください。
-### プログレスイベントをリッスンする - -アプリケーションによって大量のデータが転送され、転送に時間がかかることがあります。 -ファイルのアップロードは典型的な例です。 -そのような転送の進捗状況に関するフィードバックを提供することにより、ユーザーによりよい経験を提供します。 - -プログレスイベントを有効にしてリクエストを行うには、`reportProgress`オプションをtrueに設定して`HttpRequest`のインスタンスを作成し、プログレスイベントを追跡できるようにします。 - - - - - -
- -すべてのプログレスイベントは変更検知をトリガーします。したがって、UIで進捗状況を本当に報告するつもりの場合にのみ、それらを有効にしてください。 - -[`HttpClient#request()`](api/common/http/HttpClient#request)でHTTPメソッドを使うときには、 -[`observe: 'events'`](api/common/http/HttpClient#request)で転送のプログレスを含むすべてのイベントを見るように設定してください。 - -
- -次に、このリクエストオブジェクトを`HttpClient.request()`メソッドに渡します。 -このメソッドは、インターセプターによって処理された同じイベントである`HttpEvents`の`Observable`を返します。 - - - - -`getEventMessage`メソッドは、イベントストリーム中の各タイプの`HttpEvent`を解釈します。 - - - - -
- -このガイドのサンプルアプリケーションには、アップロードされたファイルを受け入れるサーバーがありません。 -`app/http-interceptors/upload-interceptor.ts`の`UploadInterceptor`は、アップロードリクエストにインターセプトし、シミュレートされたイベントのObservableを返して省略します。 +## セキュリティ:XSRF保護 {@a security-xsrf-protection} - -
- -## セキュリティ: XSRFプロテクション {@a security-xsrf-protection} - -[XSRF(Cross-Site Request Forgery)](https://en.wikipedia.org/wiki/Cross-site_request_forgery)は、攻撃者が認証されたユーザーにそうとは知らずにあなたのWebサイト上のアクションを実行させる攻撃手法です。 +[Cross-Site Request Forgery (XSRF or CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery)は、攻撃者が認証されたユーザーにそうとは知らずにあなたのWebサイト上のアクションを実行させる攻撃手法です。 `HttpClient`は、XSRF攻撃を防ぐための[共通メカニズム](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token)をサポートしています。 -HTTPリクエストを実行するとき、インターセプターはデフォルトでは`XSRF-TOKEN`によってクッキーからトークンを読み込み、それをHTTPヘッダの`X-XSRF-TOKEN`として設定します。 -ドメイン上で動作するコードだけがクッキーを読み取ることができるため、バックエンドはHTTPリクエストが攻撃者ではなくクライアントアプリケーションからのものであることを保証できます。 - -デフォルトでは、インターセプターは相対URLへのすべての変更リクエスト(POSTなど)に対してこのヘッダーを送信しますが、GET/HEADリクエストや絶対URLには送りません。 +HTTPリクエストを実行するとき、インターセプターはクッキーからトークンを読み取り(デフォルトでは「XSRF-TOKEN」)、それをHTTPヘッダの`X-XSRF-TOKEN`として設定します。 +ドメインで実行されているコードのみがクッキーを読み取ることができるため、バックエンドはHTTPリクエストが攻撃者ではなくクライアントアプリケーションから送信されたことを確認できます。 +デフォルトでは、インターセプターは相対URLへのすべての変更リクエスト(POSTなど)に対してこのヘッダーを送信しますが、 +GET/HEADリクエストや絶対URLには送りません。 これを利用するには、サーバーがページ読み込みまたは最初のGETリクエストのいずれかで、`XSRF-TOKEN`というJavaScriptで読み取れるセッションクッキーにトークンを設定する必要があります。 -その後のリクエストでは、サーバーはクッキーが`X-XSRF-TOKEN` HTTPヘッダーと一致することを検証でき、したがって、ドメイン上で実行されているコードだけがリクエストを送信できたと確認できます。 +その後のリクエストで、サーバーはクッキーが`X-XSRF-TOKEN`HTTPヘッダーと一致することを検証でき、よって、ドメイン上で実行されているコードだけがリクエストを送信可能だと保証できます。 トークンは、各ユーザーごとに一意でなければならず、サーバーによって検証可能でなければなりません。これにより、クライアントは独自のトークンを作成することができなくなります。 -セキュリティを強化するために、サイトの認証クッキーのダイジェストをソルトを用いてトークンに設定します。 +セキュリティを強化するために、ソルトをつけたサイトの認証クッキーのダイジェストをトークンに設定します。 複数のAngularアプリケーションが同じドメインまたはサブドメインを共有する環境での衝突を防ぐために、各アプリケーションに固有のクッキー名を付けましょう。
-*`HttpClient`のサポートはクライアント側だけの、XSRFプロテクションのスキームの半分です。* -あなたのバックエンドサービスは、ページのクッキーを設定し、 -該当するすべてのリクエストにヘッダが存在することを検証するように構成する必要があります。 +*`HttpClient`は、XSRFプロテクションのスキームの半分であるクライアント側をサポートするのみです。* +バックエンドサービスは、ページのクッキーを設定し、 +該当するすべてのリクエストにヘッダーが存在することを検証するように構成する必要があります。 そうでない場合、Angularのデフォルトの保護は効果がありません。
### カスタムのクッキー/ヘッダーの名前を設定する -バックエンドサービスがXSRFトークンのクッキーまたはヘッダーに異なる名前を使っている場合、`HttpClientXsrfModule.withConfig()`を使用してデフォルト設定を上書きします。 - +バックエンドサービスがXSRFトークンのクッキーまたはヘッダーに異なる名前を使っている場合、 +`HttpClientXsrfModule.withOptions()`を使用してデフォルト設定を上書きします。 - +{@a testing-requests} ## HTTPリクエストをテストする {@a testing-http-requests} -外部依存関係と同様に、HTTPバックエンドをモックして、テストでリモートサーバーとのやりとりをシミュレートできるようにする必要があります。 +外部依存と同様に、テストがリモートサーバーとのやりとりをシミュレートできるようにするには、HTTPバックエンドをモックする必要があります。 `@angular/common/http/testing`ライブラリでは、そのようなモッキングを簡単に設定できます。 -Angular HTTPテストライブラリは、アプリケーションがコードを実行してリクエストを最初に行うテストパターン用に設計されています。 -そして、ある種のリクエストがあったかどうかをテストします。 -これらのリクエストに対してアサーションを実行し、最終的に各リクエストを「フラッシュ」することによってレスポンスを提供します。 +AngularのHTTPテスティングライブラリは、アプリケーションがコードを実行して最初にリクエストを行うテストパターンに向けて設計されています。 +テストは特定のリクエストが作成されたかどうかを期待し、 +リクエストに対してアサーションを実行し、 +最終的に期待された各リクエストを「フラッシュ」することによってレスポンスを提供します。 - -最後に、予期しないリクエストをしていないことを確認します。 +最後に、期待しないリクエストをしていないことを確認できます。
-実際のコーディング環境でこれらのサンプルテストを実行できます。 - +ライブコーディング環境で +これらのサンプルテストを実行できます。 このガイドで説明されているテストは、`src/testing/http-client.spec.ts`にあります。 -`src/app/heroes/heroes.service.spec.ts`に`HttpClient`を呼び出すアプリケーションデータサービスのテストもあります。 - +`src/app/heroes/heroes.service.spec.ts`に +`HttpClient`を呼び出すアプリケーションデータサービスのテストもあります。
-### セットアップ - -`HttpClient`への呼び出しをテストするには、`HttpClientTestingModule`とモックコントローラ`HttpTestingController`をテストに必要な他のシンボルと共にインポートしてください。 - +### テストのセットアップ +`HttpClient`への呼び出しをテストするには、 +`HttpClientTestingModule`とモックコントローラ`HttpTestingController`を、 +テストに必要な他のシンボルと共にインポートしてください。 - -次に`HttpClientTestingModule`を`TestBed`に追加し_テスト環境のサービス_の設定を続けます。 - +次に`HttpClientTestingModule`を`TestBed`に追加し、 +_テスト環境下のサービス_の設定を続けます。 - -テストの過程で行われたリクエストは、通常のバックエンドの代わりにテストバックエンドにヒットするでしょう。 +これで、テストの過程で行われたリクエストは、通常のバックエンドの代わりにテストバックエンドにヒットします。 -この設定では`TestBed.inject()`を呼び出してテスト中に参照できるように`HttpClient`サービスとモックコントローラを注入します。 +この設定では`TestBed.inject()`を呼び出して`HttpClient`サービスとモックコントローラを注入し、 +テスト中に参照できるようにします。 +### リクエストの期待と応答 -### リクエストの待ち受けと応答 +これで、GETリクエストの発生を期待し、モックレスポンスを提供するテストを作成できます。 -これで、GETリクエストの発生を待ち受けてモックレスポンスを提供するというテストを作成できます。 - - + region="get-test" + header="app/testing/http-client.spec.ts (HttpClient.get)"> -最後のステップは、まだ未解決のリクエストが残ってないことを確認することです。これは、`afterEach()`ステップに移動して行うことが一般的です。 +最後に残ったステップは、未解決のリクエストが残っていないことを確認することです。これは、`afterEach()`ステップに移動して行うことが一般的です。 - -#### カスタムリクエストの待ち受け +#### カスタムリクエストの期待 URLによる照合では不十分な場合は、独自の照合機能を実装することができます。 -たとえば、承認ヘッダーをもつ外部リクエストを検索できます。 +たとえば、認可ヘッダーをもつ外部へのリクエストを検索できます。 - + region="predicate"> -以前の`expectOne()`と同様に、0または2以上のリクエストがこの条件を満たしていれば、テストは失敗します。 +以前の`expectOne()`と同様に、 +0または2以上のリクエストがこの条件を満たしていれば、テストは失敗します。 #### 複数のリクエストの処理 テストで重複したリクエストに応答する必要がある場合は、`expectOne()`の代わりに`match()`APIを使用してください。 同じ引数をとりますが、一致するリクエストの配列を返します。 -戻されたこれらのリクエストは、今後の照合から削除され、 -それらをフラッシュして検証する責任があります。 +これらのリクエストは一度返されると、その後の照合から削除され、 +それらをフラッシュして検証する必要があります。 - ### エラーのテスト -失敗したHTTPリクエストに対してアプリケーションがどう防御しているかテストする必要があります。 +失敗したHTTPリクエストに対するアプリケーションの防御をテストするべきです。 次の例に示すように、エラーメッセージと共に`request.flush()`を呼び出します。 - -あるいは、`ErrorEvent`と共に`request.error()`を呼び出すこともできます。 +あるいは、`ProgressEvent`と共に`request.error()`を呼び出すこともできます。 + + +## メタデータをインターセプターに渡す + +多くのインターセプターは、設定を必要とするか、設定から恩恵を受けます。失敗したリクエストを再試行するインターセプターについて考えてみます。 +デフォルトでは、インターセプターはリクエストを3回再試行してよいですが、特にエラーが発生しやすいリクエストや機密性の高いリクエストの場合は、この再試行回数を上書きしたくなるでしょう。 + +`HttpClient`リクエストには、リクエストに関するメタデータを運ぶことができる_コンテキスト_が含まれています。 +このコンテキストは、インターセプターが読み取りまたは変更するために使用できますが、リクエスト送信時にバックエンドサーバーには送信されません。 +これにより、アプリケーションまたは他のインターセプターは、リクエストに対しリクエストを再試行する回数などの設定パラメーターを付加できます。 + +### コンテキストトークンの作成 + +Angularは、`HttpContextToken`を使用してコンテキスト内への値の格納とコンテキストからの値の取得を行います。 +次の例のように、`new`オペレーターを使用してコンテキストトークンを作成できます。 + + + +`HttpContextToken`の作成中に渡されるラムダ関数`() => 3`は2つの目的を果たします。 + +1. このトークンの型を、`HttpContextToken`とTypeScriptが推論できるようにします。 + リクエストコンテキストは型安全です。—リクエストのコンテキストからトークンを読み取ると、適切な型の値が返されます。 + +1. トークンのデフォルト値を設定します。 + これは、このトークンに他の値が設定されていない場合にリクエストコンテキストが返す値です。 + デフォルト値を使用すると、個々の値が設定されているかどうかを確認する必要がなくなります。 + +### リクエスト作成時にコンテキスト値を設定する + +リクエストを作成するときに、`HttpContext`インスタンスを提供できます。これにはコンテキスト値を設定済みです。 + + + +### インターセプターでのコンテキスト値の読み取り + +インターセプター内では、`HttpContext.get()`を使用して、与えられたリクエストのコンテキストでトークンの値を読み取ることができます。 +トークンの値を明示的に設定していない場合、Angularはトークンに指定されたデフォルト値を返します。 + + + +### コンテキストはミュータブル + +`HttpRequest`インスタンスの他の多くの性質とは異なり、リクエストコンテキストはミュータブルであり、リクエストの他のイミュータブルな変換にまたがって持続します。 +これにより、インターセプターはコンテキストを介してオペレーターを協調して動作させることができます。 +たとえば、`RetryInterceptor`の例では、2番目のコンテキストトークンを使用して、特定のリクエストの実行中に発生したエラーの数を追跡できます。 + + diff --git a/aio-ja/content/guide/hydration.md b/aio-ja/content/guide/hydration.md index 8866e6957a..023d8cf388 100644 --- a/aio-ja/content/guide/hydration.md +++ b/aio-ja/content/guide/hydration.md @@ -65,7 +65,13 @@ After you've followed these steps and have started up your server, load your app
-While running an application in dev mode, you can confirm hydration is enabled by opening the Developer Tools in your browser and viewing the console. You should see a message that includes hydration-related stats, such as the number of components and nodes hydrated. Note: Angular calculates the stats based on all components rendered on a page, including those that come from third-party libraries. +While running an application in dev mode, you can confirm hydration is enabled by opening the Developer Tools in your browser and viewing the console. You should see a message that includes hydration-related stats, such as the number of components and nodes hydrated. + +
+ +Angular calculates the stats based on all components rendered on a page, including those that come from third-party libraries. + +
@@ -91,6 +97,8 @@ This is because Angular is unaware of these DOM changes and cannot resolve them It is best to refactor your component to avoid this sort of DOM manipulation. Try to use Angular APIs to do this work, if you can. If you cannot refactor this behavior, use the `ngSkipHydration` attribute ([described below](#ngskiphydration)) until you can refactor into a hydration friendly solution. + + ### Valid HTML structure There are a few cases where if you have a component template that does not have valid HTML structure, this could result in a DOM mismatch error during hydration. @@ -128,7 +136,7 @@ Providing a custom or a "noop" Zone.js implementation may lead to a different ti ## Errors -There are several hydration related errors you may encounter ranging from node mismatches to cases when the `ngSkipHydration` was used on an invalid host node. The most common error case that may occur is due to direct DOM manipulation using native APIs that results in hydration being unable to find or match the expected DOM tree structure on the client that was rendered by the server. The other case you may encounter this type of error was mentioned in the prior section on Valid HTML structures. So, make sure the HTML in your templates are using valid structure, and you'll avoid that error case. +There are several hydration related errors you may encounter ranging from node mismatches to cases when the `ngSkipHydration` was used on an invalid host node. The most common error case that may occur is due to direct DOM manipulation using native APIs that results in hydration being unable to find or match the expected DOM tree structure on the client that was rendered by the server. The other case you may encounter this type of error was mentioned in the [Valid HTML structure](#valid-html) section earlier. So, make sure the HTML in your templates are using valid structure, and you'll avoid that error case. For a full reference on hydration related errors, visit the [Errors Reference Guide](/errors). @@ -136,7 +144,7 @@ For a full reference on hydration related errors, visit the [Errors Reference Gu ## How to skip hydration for particular components -Some components may not work properly with hydration enabled due to some of the aforementioned issues, like direct DOM manipulation. As a workaround, you can add the `ngSkipHydration` attribute to a component's tag in order to skip hydrating the entire component. +Some components may not work properly with hydration enabled due to some of the aforementioned issues, like [Direct DOM Manipulation](#dom-manipulation). As a workaround, you can add the `ngSkipHydration` attribute to a component's tag in order to skip hydrating the entire component. ```html @@ -175,3 +183,5 @@ re-rendering those components from scratch. ## Third Party Libraries with DOM Manipulation There are a number of third party libraries that depend on DOM manipulation to be able to render. D3 charts is a prime example. These libraries worked without hydration, but they may cause DOM mismatch errors when hydration is enabled. For now, if you encounter DOM mismatch errors using one of these libraries, you can add the `ngSkipHydration` attribute to the component that renders using that library. + +@reviewed 2023-06-21 diff --git a/aio-ja/content/guide/i18n-common-prepare.en.md b/aio-ja/content/guide/i18n-common-prepare.en.md index 7d51325a8b..352bb50269 100644 --- a/aio-ja/content/guide/i18n-common-prepare.en.md +++ b/aio-ja/content/guide/i18n-common-prepare.en.md @@ -196,8 +196,8 @@ The following code example shows the value of the [`$localize`][AioApiLocalizeIn
-
- How meanings control text extraction and merges +
+How meanings control text extraction and merges
The Angular extraction tool generates a translation unit entry for each `i18n` attribute in a template. @@ -306,9 +306,7 @@ For more information about pluralization categories, see [Choosing plural catego
- - -
Background: Locales may not support some pluralization categories
+
Background: Locales may not support some pluralization categories
Many locales don't support some of the pluralization categories. The default locale \(`en-US`\) uses a very simple `plural()` function that doesn't support the `few` pluralization category. diff --git a/aio-ja/content/guide/i18n-common-prepare.md b/aio-ja/content/guide/i18n-common-prepare.md index 20f28b660e..28b24d47a8 100644 --- a/aio-ja/content/guide/i18n-common-prepare.md +++ b/aio-ja/content/guide/i18n-common-prepare.md @@ -196,8 +196,8 @@ i18nメタデータはコロン\(`:`\)で囲まれ、翻訳元テキストの前
-
- テキスト抽出と結合を制御する方法 +
+テキスト抽出と結合を制御する方法
Angularの抽出ツールは、テンプレート内の`i18n`属性ごとに翻訳単位エントリを生成します。 @@ -306,9 +306,7 @@ other { default_quantity }
- - -
背景: ロケールはいくつかの複数形カテゴリをサポートしません
+
背景: ロケールはいくつかの複数形カテゴリをサポートしません
多くのロケールでは、複数形カテゴリーのいくつかをサポートしていません。 デフォルトのロケール \(`en-US`\)は非常に単純な`plural()`関数を使用しており、`few`複数形カテゴリーをサポートしていません。 diff --git a/aio-ja/content/guide/image-directive.en.md b/aio-ja/content/guide/image-directive.en.md index 60bc285db3..3a8e169922 100644 --- a/aio-ja/content/guide/image-directive.en.md +++ b/aio-ja/content/guide/image-directive.en.md @@ -17,6 +17,8 @@ In addition to optimizing the loading of the LCP image, `NgOptimizedImage` enfor * Warning if `width` or `height` have been set incorrectly * Warning if the image will be visually distorted when rendered +**Note: Although the `NgOptimizedImage` directive was made a stable feature in Angular version 15, it has been backported and is available as a stable feature in versions 13.4.0 and 14.3.0 as well. ** + ## Getting Started #### Step 1: Import NgOptimizedImage @@ -75,7 +77,7 @@ In order to prevent [image-related layout shifts](https://web.dev/css-web-vitals -For **responsive images** (images which you've styled to grow and shrink relative to the viewport), the `width` and `height` attributes should be the instrinsic size of the image file. +For **responsive images** (images which you've styled to grow and shrink relative to the viewport), the `width` and `height` attributes should be the instrinsic size of the image file. For responsive images it's also important to [set a value for `sizes`.](#responsive-images) For **fixed size images**, the `width` and `height` attributes should reflect the desired rendered size of the image. The aspect ratio of these attributes should always match the intrinsic aspect ratio of the image. @@ -312,10 +314,33 @@ Note that in the above example, we've invented the 'roundedCorners' property nam +## Frequently Asked Questions + +### Does NgOptimizedImage support the `background-image` css property? +The NgOptimizedImage does not directly support the `background-image` css property, but it is designed to easily accommodate the use case of having an image as the background of another element. + +Here's a simple step-by-step process for migrating from `background-image` to `NgOptimizedImage`. For these steps, we'll refer to the element that has an image background as the "containing element": + +1) Remove the `background-image` style from the containing element. +2) Ensure that the containing element has `position: "relative"`, `position: "fixed"`, or `position: "absolute"`. +3) Create a new image element as a child of the containing element, using `ngSrc` to enable the `NgOptimizedImage` directive. +4) Give that element the `fill` attribute. Do not include a `height` and `width`. +5) If you believe this image might be your [LCP element](https://web.dev/lcp/), add the `priority` attribute to the image element. + +You can adjust how the background image fills the container as described in the [Using fill mode](#using-fill-mode) section. + +### Why can't I use `src` with `NgOptimizedImage`? +The `ngSrc` attribute was chosen as the trigger for NgOptimizedImage due to technical considerations around how images are loaded by the browser. NgOptimizedImage makes programmatic changes to the `loading` attribute--if the browser sees the `src` attribute before those changes are made, it will begin eagerly downloading the image file, and the loading changes will be ignored. + +### Can I use two different image domains in the same page? +The [image loaders](#configuring-an-image-loader-for-ngoptimizedimage) provider pattern is designed to be as simple as possible for the common use case of having only a single image CDN used within a component. However, it's still very possible to manage multiple image CDNs using a single provider. + +To do this, we recommend writing a [custom image loader](#custom-loaders) which uses the [`loaderParams` property](#the-loaderparams-property) to pass a flag that specifies which image CDN should be used, and then invokes the appropriate loader based on that flag. + -@reviewed 2022-11-07 +@reviewed 2023-07-18 diff --git a/aio-ja/content/guide/image-directive.md b/aio-ja/content/guide/image-directive.md index 9db9d71aab..309d0b32e5 100644 --- a/aio-ja/content/guide/image-directive.md +++ b/aio-ja/content/guide/image-directive.md @@ -19,6 +19,8 @@ LCP 画像の読み込みを最適化することに加えて、`NgOptimizedImag * `width` または `height` が正しく設定されていない場合に警告する * レンダリング時に画像が視覚的に歪む場合に警告する +**Note: Although the `NgOptimizedImage` directive was made a stable feature in Angular version 15, it has been backported and is available as a stable feature in versions 13.4.0 and 14.3.0 as well. ** + ## Getting Started #### Step 1: Import NgOptimizedImage @@ -77,7 +79,7 @@ In order to prevent [image-related layout shifts](https://web.dev/css-web-vitals -For **responsive images** (images which you've styled to grow and shrink relative to the viewport), the `width` and `height` attributes should be the instrinsic size of the image file. +For **responsive images** (images which you've styled to grow and shrink relative to the viewport), the `width` and `height` attributes should be the instrinsic size of the image file. For responsive images it's also important to [set a value for `sizes`.](#responsive-images) For **fixed size images**, the `width` and `height` attributes should reflect the desired rendered size of the image. The aspect ratio of these attributes should always match the intrinsic aspect ratio of the image. @@ -313,10 +315,33 @@ Note that in the above example, we've invented the 'roundedCorners' property nam +## Frequently Asked Questions + +### Does NgOptimizedImage support the `background-image` css property? +The NgOptimizedImage does not directly support the `background-image` css property, but it is designed to easily accommodate the use case of having an image as the background of another element. + +Here's a simple step-by-step process for migrating from `background-image` to `NgOptimizedImage`. For these steps, we'll refer to the element that has an image background as the "containing element": + +1) Remove the `background-image` style from the containing element. +2) Ensure that the containing element has `position: "relative"`, `position: "fixed"`, or `position: "absolute"`. +3) Create a new image element as a child of the containing element, using `ngSrc` to enable the `NgOptimizedImage` directive. +4) Give that element the `fill` attribute. Do not include a `height` and `width`. +5) If you believe this image might be your [LCP element](https://web.dev/lcp/), add the `priority` attribute to the image element. + +You can adjust how the background image fills the container as described in the [Using fill mode](#using-fill-mode) section. + +### Why can't I use `src` with `NgOptimizedImage`? +The `ngSrc` attribute was chosen as the trigger for NgOptimizedImage due to technical considerations around how images are loaded by the browser. NgOptimizedImage makes programmatic changes to the `loading` attribute--if the browser sees the `src` attribute before those changes are made, it will begin eagerly downloading the image file, and the loading changes will be ignored. + +### Can I use two different image domains in the same page? +The [image loaders](#configuring-an-image-loader-for-ngoptimizedimage) provider pattern is designed to be as simple as possible for the common use case of having only a single image CDN used within a component. However, it's still very possible to manage multiple image CDNs using a single provider. + +To do this, we recommend writing a [custom image loader](#custom-loaders) which uses the [`loaderParams` property](#the-loaderparams-property) to pass a flag that specifies which image CDN should be used, and then invokes the appropriate loader based on that flag. + -@reviewed 2022-11-07 +@reviewed 2023-07-18 diff --git a/aio-ja/content/guide/inputs-outputs.en.md b/aio-ja/content/guide/inputs-outputs.en.md index 357322017e..6263110ba8 100644 --- a/aio-ja/content/guide/inputs-outputs.en.md +++ b/aio-ja/content/guide/inputs-outputs.en.md @@ -207,6 +207,33 @@ The property `currentItem` and the method `crossOffItem()` are both in the paren To combine property and event bindings using the banana-in-a-box syntax, `[()]`, see [Two-way Binding](guide/two-way-binding). +## Additional Configurations +### Configuring the child component input as required field + +To make `Input` property as required for a child component while passing values from parent component. first import `Input` and then decorate the property with `@Input({ required: true })`, as in the following example. + + + +Next, in the parent template add the following: + + + +If required inputs `property binding` in a child component are not specified in the parent component template will result a compile time error : + +
+NG8008: Required input item from component ItemDetailMetadataComponent must be specified. +
+ +### Configuring the child component input with transform functions + +To transform an `Input` property from string to boolean to a child component while passing values from parent component. first import `booleanAttribute` and then decorate the property with `@Input({ transform: booleanAttribute })`, as in the following example. + + + + + +Similarly, you can use predefined functions from angular/core library to convert string to number as well, see `numberAttribute`. + diff --git a/aio-ja/content/guide/inputs-outputs.md b/aio-ja/content/guide/inputs-outputs.md index 3112371957..9eeee3067e 100644 --- a/aio-ja/content/guide/inputs-outputs.md +++ b/aio-ja/content/guide/inputs-outputs.md @@ -200,4 +200,37 @@ delete をクリックすると、子コンポーネントはイベント `delet banana-in-a-box 構文 `[()]` を使うことで、プロパティとイベントバインディングを合体させることができます。 詳しくは[双方向バインディング](guide/two-way-binding)をご覧ください。 -@reviewed 2021-09-17 +## Additional Configurations +### Configuring the child component input as required field + +To make `Input` property as required for a child component while passing values from parent component. first import `Input` and then decorate the property with `@Input({ required: true })`, as in the following example. + + + +Next, in the parent template add the following: + + + +If required inputs `property binding` in a child component are not specified in the parent component template will result a compile time error : + +
+NG8008: Required input item from component ItemDetailMetadataComponent must be specified. +
+ +### Configuring the child component input with transform functions + +To transform an `Input` property from string to boolean to a child component while passing values from parent component. first import `booleanAttribute` and then decorate the property with `@Input({ transform: booleanAttribute })`, as in the following example. + + + + + +Similarly, you can use predefined functions from angular/core library to convert string to number as well, see `numberAttribute`. + + + + + + + +@reviewed 2022-02-28 diff --git a/aio-ja/content/guide/lifecycle-hooks.en.md b/aio-ja/content/guide/lifecycle-hooks.en.md index bd800810b2..864c150758 100644 --- a/aio-ja/content/guide/lifecycle-hooks.en.md +++ b/aio-ja/content/guide/lifecycle-hooks.en.md @@ -101,7 +101,7 @@ The `ngOnDestroy()` method is also the time to notify another part of the applic ### DestroyRef -In addition to to `ngOnDestroy()`, you can inject Angular's `DestroyRef` and register callback functions to be called when the enclosing context is destroyed. This can be useful for building reusable utilities that require cleanup. +In addition to `ngOnDestroy()`, you can inject Angular's `DestroyRef` and register callback functions to be called when the enclosing context is destroyed. This can be useful for building reusable utilities that require cleanup. Register a callback with the `DestroyRef`: @@ -136,7 +136,98 @@ When using RxJS Observables in components or directives, you may want to complet data$ = http.get('...').pipe(takeUntilDestroyed()); ``` -By default, `takeUntilDestroyed` must be called in an injection context so that it can access `DestroyRef`. If an injection context isn't available, you can explicitly provide a `DestroyRef`. +By default, `takeUntilDestroyed` must be called in an [injection context](/guide/dependency-injection-context) so that it can access `DestroyRef`. If an injection context isn't available, you can explicitly provide a `DestroyRef`. + +## Reading and writing the DOM + +Sometimes it's necessary to use browser-only APIs to manually read or write the DOM. This can be challenging to do with the [lifecycle events](#lifecycle-event-sequence) above, as they will also run during [server-side rendering and pre-rendering](guide/glossary#server-side-rendering). For this purpose, Angular provides `afterRender` and `afterNextRender`. These functions can be used unconditionally, but will only have an effect on the browser. Both functions accept a callback that will run after the next [change detection](/guide/glossary#change-detection) cycle (including any nested cycles) has completed. + +
+ +`afterRender` and `afterNextRender` are available for [developer preview](/guide/releases#developer-preview). They are ready for you to try, but they might change before they are stable. + +
+ +| Function | Purpose | Timing | +| ------ | ------- | ------ | +| `afterNextRender` | Perform one-time initialization, or observe a single, specific change to the DOM.
As a rule of thumb, you should use `afterRender` instead if you need to manually read or write any layout data such as size or location.
See details in [One-time initialization](#one-time-initialization) in this document. | _Once_ after the next change detection cycle. | +| `afterRender` | Synchronize state with the DOM. See details in [Handling synchronization](#handling-synchronization) in this document. | After _every_ change detection cycle that follows. | + +### One-time initialization + +Generally, you will want to use `afterNextRender` to perform any one-time initialization, such as for a third-party library, or for browser-only APIs. + +```ts +@Component({ + selector: 'my-chart-cmp', + template: `
{{ ... }}
`, +}) +export class MyChartCmp { + @ViewChild('chart') chartRef: ElementRef; + chart: MyChart|null; + + constructor() { + afterNextRender(() => { + this.chart = new MyChart(this.chartRef.nativeElement); + }); + } +} +``` + +Instead of attempting to recreate their behaviors with `afterRender`, you should prefer to use built-in browser APIs like `ResizeObserver` and `IntersectionObserver` wherever possible. You can use `afterNextRender` to safely initialize such APIs on the browser only. + +```ts +@Component({ + selector: 'my-cmp', + template: `{{ ... }}`, +}) +export class MyComponent { + resizeObserver: ResizeObserver|null = null; + @ViewChild('content') contentRef: ElementRef; + + constructor() { + afterNextRender(() => { + this.resizeObserver = new ResizeObserver(() => { + console.log('Content was resized'); + }); + + this.resizeObserver.observe(this.contentRef.nativeElement); + }); + } + + ngOnDestroy() { + this.resizeObserver?.disconnect(); + this.resizeObserver = null; + } +} +``` + +
+ +As a rule of thumb, `afterNextRender` should be used to observe _discrete_ changes to the DOM, such as element creation or deletion. For manually reading or writing data that tends to change frequently, such as size or location, you should generally prefer to use `afterRender` instead. + +
+ +### Handling synchronization + +As an escape hatch for when the browser does not provide a better API to do so, you can use `afterRender` to perform any additional read or writes to the DOM every time Angular finishes mutating it. + +```ts +@Component({ + selector: 'my-cmp', + template: `{{ ... }}`, +}) +export class MyComponent { + @ViewChild('content') contentRef: ElementRef; + + constructor() { + afterRender(() => { + const elem = this.contentRef.nativeElement; + console.log(`content position: (${elem.offsetLeft}, ${elem.offsetTop})`); + }); + } +} +``` ## General examples diff --git a/aio-ja/content/guide/lifecycle-hooks.md b/aio-ja/content/guide/lifecycle-hooks.md index d3a9df0e5a..d51a1eea5b 100644 --- a/aio-ja/content/guide/lifecycle-hooks.md +++ b/aio-ja/content/guide/lifecycle-hooks.md @@ -14,7 +14,7 @@ Angular は実行中にインスタンスを作成、更新、破棄するため * [TypeScript プログラミング](https://www.typescriptlang.org/) * [Angularの概念](guide/architecture "Introduction to fundamental app-design concepts") で説明されている Angular アプリケーションの設計の基礎。 -{@a hooks-overview} + ## ライフサイクルイベントへの応答 @@ -30,7 +30,7 @@ Angular の `core` ライブラリ中の 1 つ以上の *ライフサイクル {@a hooks-purpose-timing} -### ライフサイクルイベントシーケンス +### ライフサイクルイベントシーケンス {@a lifecycle-event-sequence} アプリケーションがそのコンストラクターを呼び出してコンポーネントまたはディレクティブをインスタンス化した後、 Angular はそのインスタンスのライフサイクルの適切な時点で実装したフックメソッドを呼び出します。 @@ -375,7 +375,98 @@ When using RxJS Observables in components or directives, you may want to complet data$ = http.get('...').pipe(takeUntilDestroyed()); ``` -By default, `takeUntilDestroyed` must be called in an injection context so that it can access `DestroyRef`. If an injection context isn't available, you can explicitly provide a `DestroyRef`. +By default, `takeUntilDestroyed` must be called in an [injection context](/guide/dependency-injection-context) so that it can access `DestroyRef`. If an injection context isn't available, you can explicitly provide a `DestroyRef`. + +## Reading and writing the DOM + +Sometimes it's necessary to use browser-only APIs to manually read or write the DOM. This can be challenging to do with the [lifecycle events](#lifecycle-event-sequence) above, as they will also run during [server-side rendering and pre-rendering](guide/glossary#server-side-rendering). For this purpose, Angular provides `afterRender` and `afterNextRender`. These functions can be used unconditionally, but will only have an effect on the browser. Both functions accept a callback that will run after the next [change detection](/guide/glossary#change-detection) cycle (including any nested cycles) has completed. + +
+ +`afterRender` and `afterNextRender` are available for [developer preview](/guide/releases#developer-preview). They are ready for you to try, but they might change before they are stable. + +
+ +| Function | Purpose | Timing | +| ------ | ------- | ------ | +| `afterNextRender` | Perform one-time initialization, or observe a single, specific change to the DOM.
As a rule of thumb, you should use `afterRender` instead if you need to manually read or write any layout data such as size or location.
See details in [One-time initialization](#one-time-initialization) in this document. | _Once_ after the next change detection cycle. | +| `afterRender` | Synchronize state with the DOM. See details in [Handling synchronization](#handling-synchronization) in this document. | After _every_ change detection cycle that follows. | + +### One-time initialization + +Generally, you will want to use `afterNextRender` to perform any one-time initialization, such as for a third-party library, or for browser-only APIs. + +```ts +@Component({ + selector: 'my-chart-cmp', + template: `
{{ ... }}
`, +}) +export class MyChartCmp { + @ViewChild('chart') chartRef: ElementRef; + chart: MyChart|null; + + constructor() { + afterNextRender(() => { + this.chart = new MyChart(this.chartRef.nativeElement); + }); + } +} +``` + +Instead of attempting to recreate their behaviors with `afterRender`, you should prefer to use built-in browser APIs like `ResizeObserver` and `IntersectionObserver` wherever possible. You can use `afterNextRender` to safely initialize such APIs on the browser only. + +```ts +@Component({ + selector: 'my-cmp', + template: `{{ ... }}`, +}) +export class MyComponent { + resizeObserver: ResizeObserver|null = null; + @ViewChild('content') contentRef: ElementRef; + + constructor() { + afterNextRender(() => { + this.resizeObserver = new ResizeObserver(() => { + console.log('Content was resized'); + }); + + this.resizeObserver.observe(this.contentRef.nativeElement); + }); + } + + ngOnDestroy() { + this.resizeObserver?.disconnect(); + this.resizeObserver = null; + } +} +``` + +
+ +As a rule of thumb, `afterNextRender` should be used to observe _discrete_ changes to the DOM, such as element creation or deletion. For manually reading or writing data that tends to change frequently, such as size or location, you should generally prefer to use `afterRender` instead. + +
+ +### Handling synchronization + +As an escape hatch for when the browser does not provide a better API to do so, you can use `afterRender` to perform any additional read or writes to the DOM every time Angular finishes mutating it. + +```ts +@Component({ + selector: 'my-cmp', + template: `{{ ... }}`, +}) +export class MyComponent { + @ViewChild('content') contentRef: ElementRef; + + constructor() { + afterRender(() => { + const elem = this.contentRef.nativeElement; + console.log(`content position: (${elem.offsetLeft}, ${elem.offsetTop})`); + }); + } +} +``` ## 一般的な例 diff --git a/aio-ja/content/guide/localized-documentation.md b/aio-ja/content/guide/localized-documentation.md index 47ea211749..7e5bb01bf8 100644 --- a/aio-ja/content/guide/localized-documentation.md +++ b/aio-ja/content/guide/localized-documentation.md @@ -2,7 +2,6 @@ This topic lists localized versions of the Angular documentation. -* [Español](http://docs.angular.lat) * [简体中文版](https://angular.cn) * [正體中文版](https://angular.tw) * [日本語版](https://angular.jp) diff --git a/aio-ja/content/guide/npm-packages.en.md b/aio-ja/content/guide/npm-packages.en.md index d1e555b96c..5cd097ee34 100644 --- a/aio-ja/content/guide/npm-packages.en.md +++ b/aio-ja/content/guide/npm-packages.en.md @@ -68,7 +68,7 @@ For a complete list of Angular packages, see the [API reference](api?type=packag | Package name | Details | |:--- |:--- | | [`@angular/animations`](api/animations) | Angular's animations library makes it easy to define and apply animation effects such as page and list transitions. For more information, see the [Animations guide](guide/animations). | -| [`@angular/common`](api/common) | The commonly-needed services, pipes, and directives provided by the Angular team. The [`HttpClientModule`](api/common/http/HttpClientModule) is also here, in the [`@angular/common/http`](api/common/http) subfolder. For more information, see the [HttpClient guide](guide/http). | +| [`@angular/common`](api/common) | The commonly-needed services, pipes, and directives provided by the Angular team. The [`HttpClientModule`](api/common/http/HttpClientModule) is also here, in the [`@angular/common/http`](api/common/http) subfolder. For more information, see the [HttpClient guide](guide/understanding-communicating-with-http). | | `@angular/compiler` | Angular's template compiler. It understands templates and can convert them to code that makes the application run and render. Typically you don't interact with the compiler directly; rather, you use it indirectly using `platform-browser-dynamic` when JIT compiling in the browser. For more information, see the [Ahead-of-time Compilation guide](guide/aot-compiler). | | [`@angular/core`](api/core) | Critical runtime parts of the framework that are needed by every application. Includes all metadata decorators, `Component`, `Directive`, dependency injection, and the component lifecycle hooks. | | [`@angular/forms`](api/forms) | Support for both [template-driven](guide/forms) and [reactive forms](guide/reactive-forms). For information about choosing the best forms approach for your app, see [Introduction to forms](guide/forms-overview). | diff --git a/aio-ja/content/guide/npm-packages.md b/aio-ja/content/guide/npm-packages.md index b700b97d97..57e16fae05 100644 --- a/aio-ja/content/guide/npm-packages.md +++ b/aio-ja/content/guide/npm-packages.md @@ -66,7 +66,7 @@ Angularのパッケージの完全な一覧は、[API reference](api?type=packag パッケージ名 | 説明 ---------------------------------------- | -------------------------------------------------- [**@angular/animations**](api/animations) | Angularのアニメーションライブラリを使用すると、ページやリストのトランジションといったアニメーション効果を簡単に定義して適用できます。詳しくは [Animations guide](guide/animations) を見てください。. -[**@angular/common**](api/common) | 一般的に必要なサービスやパイプ、ディレクティブがAngularチームによって提供されています。 [`HttpClientModule`](api/common/http/HttpClientModule) もここの [`@angular/common/http`](api/common/http) というサブフォルダにあります。詳しくは [HttpClient guide](guide/http) を見てください。 +[**@angular/common**](api/common) | 一般的に必要なサービスやパイプ、ディレクティブがAngularチームによって提供されています。 [`HttpClientModule`](api/common/http/HttpClientModule) もここの [`@angular/common/http`](api/common/http) というサブフォルダにあります。詳しくは [HttpClient guide](guide/understanding-communicating-with-http) を見てください。 **@angular/compiler** | Angularのテンプレートのコンパイラです。テンプレートを解釈し、アプリケーションが実行・表示可能なコードに変換します。 通常はコンパイラに直接触れないでください。そうではなくブラウザ上でJITコンパイルするときに `platform-browser-dynamic` を通して間接的に使用します。詳しくは [Ahead-of-time Compilation guide](guide/aot-compiler)を見てください。 [**@angular/core**](api/core) | すべてのアプリケーションに必要とされるフレームワークの重要なランタイム部分です。すべてのメタデータデコレーター、`Component` 、 `Directive `、依存性の注入、コンポーネントのライフサイクルフックを含みます。 [**@angular/forms**](api/forms) | [テンプレート駆動のフォーム](guide/forms)と[リアクティブフォーム](guide/reactive-forms)の両方をサポートします。アプリケーションに最適なフォームアプローチの選択についての情報は [Introduction to forms](guide/forms-overview) を見てください。 diff --git a/aio-ja/content/guide/pipes.md b/aio-ja/content/guide/pipes.md index 3ee48eaf83..6fe4d32d4a 100644 --- a/aio-ja/content/guide/pipes.md +++ b/aio-ja/content/guide/pipes.md @@ -335,7 +335,7 @@ The following code example binds an observable of message strings ## Caching HTTP requests -To [communicate with backend services using HTTP](guide/http "Communicating with backend services using HTTP"), the `HttpClient` service uses observables and offers the `HttpClient.get()` method to fetch data from a server. +To [communicate with backend services using HTTP](guide/understanding-communicating-with-http "Communicating with backend services using HTTP"), the `HttpClient` service uses observables and offers the `HttpClient.get()` method to fetch data from a server. The asynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response. As shown in the previous section, use the impure `AsyncPipe` to accept an observable as input and subscribe to the input automatically. diff --git a/aio-ja/content/guide/releases.en.md b/aio-ja/content/guide/releases.en.md index f1c43e9ce7..10014c67b3 100644 --- a/aio-ja/content/guide/releases.en.md +++ b/aio-ja/content/guide/releases.en.md @@ -113,7 +113,7 @@ Approximate dates are offered as general guidance and are subject to change. | Version | Date | |:--------|:-------------------| | v16.1 | Week of 2023-06-12 | -| v16.2 | Week of 2023-07-24 | +| v16.2 | Week of 2023-08-07 | | v17.0 | Week of 2023-11-06 | ### Support window diff --git a/aio-ja/content/guide/releases.md b/aio-ja/content/guide/releases.md index bcda07be74..8f95271293 100644 --- a/aio-ja/content/guide/releases.md +++ b/aio-ja/content/guide/releases.md @@ -105,7 +105,7 @@ Angularプロジェクトを最新バージョンにアップデートする方 | Version | Date | |:--------|:-------------------| | v16.1 | Week of 2023-06-12 | -| v16.2 | Week of 2023-07-24 | +| v16.2 | Week of 2023-08-07 | | v17.0 | Week of 2023-11-06 | ### サポート期間 {@a support-window} diff --git a/aio-ja/content/guide/router-tutorial-toh.en.md b/aio-ja/content/guide/router-tutorial-toh.en.md index bbdfa275f9..28f3939ecb 100644 --- a/aio-ja/content/guide/router-tutorial-toh.en.md +++ b/aio-ja/content/guide/router-tutorial-toh.en.md @@ -578,6 +578,8 @@ Follow these steps: * Change the component class name to `HeroListComponent`. * Change the `selector` to `app-hero-list`. + * Change the `templateUrl` to `./hero-list.component.html`. + * Change the `styleUrls` to `./hero-list.component.css`.
diff --git a/aio-ja/content/guide/router-tutorial-toh.md b/aio-ja/content/guide/router-tutorial-toh.md index 981fc92f5b..95dcb2fcfb 100644 --- a/aio-ja/content/guide/router-tutorial-toh.md +++ b/aio-ja/content/guide/router-tutorial-toh.md @@ -654,6 +654,8 @@ ng generate module my-module --routing * コンポーネントのクラス名を `HeroListComponent` に変更します。 * `selector` を `app-hero-list` に変更します。 + * `templateUrl`を`./hero-list.component.html`に変更します。 + * `styleUrls`を`./hero-list.component.css`に変更します。
diff --git a/aio-ja/content/guide/router.md b/aio-ja/content/guide/router.md index 92d97bf952..1ef1032ca3 100644 --- a/aio-ja/content/guide/router.md +++ b/aio-ja/content/guide/router.md @@ -135,7 +135,9 @@ To get information from a route: **NOTE:**
You can bind all route data with key, value pairs to component inputs: static or resolved route data, path parameters, matrix parameters, and query parameters. - +
+ If you want to use the parent components route info you will need to set the router {@link paramsInheritanceStrategy} option: + `withRouterConfig({paramsInheritanceStrategy: 'always'})`
diff --git a/aio-ja/content/guide/rxjs-interop.md b/aio-ja/content/guide/rxjs-interop.md index 0f34d8a4f6..8c54d1441b 100644 --- a/aio-ja/content/guide/rxjs-interop.md +++ b/aio-ja/content/guide/rxjs-interop.md @@ -83,7 +83,7 @@ As the `query` signal changes, the `query$` Observable emits the latest query an ### Injection context -`toObservable` by default needs to run in an injection context, such as during construction of a component or service. If an injection context is not available, an `Injector` can instead be explicitly specified. +`toObservable` by default needs to run in an [injection context](/guide/dependency-injection-context), such as during construction of a component or service. If an injection context is not available, an `Injector` can instead be explicitly specified. ### Timing of `toObservable` diff --git a/aio-ja/content/guide/schematics-authoring.en.md b/aio-ja/content/guide/schematics-authoring.en.md index 2c9ba52539..84a601e31a 100644 --- a/aio-ja/content/guide/schematics-authoring.en.md +++ b/aio-ja/content/guide/schematics-authoring.en.md @@ -214,7 +214,7 @@ By using the long form, the schematic can provide more explicit formatting of th { "value": "css", "label": "CSS" }, { "value": "scss", "label": "SCSS [ https://sass-lang.com/documentation/syntax#scss ]" }, { "value": "sass", "label": "Sass [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]" }, - { "value": "less", "label": "Less [ http://lesscss.org/ ]" } + { "value": "less", "label": "Less [ https://lesscss.org/ ]" } ] }, }, diff --git a/aio-ja/content/guide/schematics-authoring.md b/aio-ja/content/guide/schematics-authoring.md index 8716106c60..f6524831eb 100644 --- a/aio-ja/content/guide/schematics-authoring.md +++ b/aio-ja/content/guide/schematics-authoring.md @@ -206,7 +206,7 @@ Schematic *prompts* は、ユーザー操作を Schematics 実行に導入しま { "value": "css", "label": "CSS" }, { "value": "scss", "label": "SCSS [ https://sass-lang.com/documentation/syntax#scss ]" }, { "value": "sass", "label": "Sass [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]" }, - { "value": "less", "label": "Less [ http://lesscss.org/ ]" } + { "value": "less", "label": "Less [ https://lesscss.org/ ]" } ] }, }, diff --git a/aio-ja/content/guide/security.en.md b/aio-ja/content/guide/security.en.md index d150ea1e17..5241796de0 100644 --- a/aio-ja/content/guide/security.en.md +++ b/aio-ja/content/guide/security.en.md @@ -13,7 +13,7 @@ You can run the in Stackblitz and download the cod
Reporting vulnerabilities
-Angular is part of Google [Open Source Software Vulnerability Reward Program](https://bughunters.google.com/about/rules/6521337925468160/google-open-source-software-vulnerability-reward-program-rules), for vulnerabilities in Angular please submit your report [here](https://bughunters.google.com/report). +Angular is part of Google [Open Source Software Vulnerability Reward Program](https://bughunters.google.com/about/rules/6521337925468160/google-open-source-software-vulnerability-reward-program-rules). [For vulnerabilities in Angular, please submit your report at https://bughunters.google.com](https://bughunters.google.com/report). For more information about how Google handles security issues, see [Google's security philosophy](https://www.google.com/about/appsecurity). @@ -344,7 +344,7 @@ That means only your application can read this cookie token and set the custom h The malicious code on `evil.com` can't. Angular's `HttpClient` has built-in support for the client-side half of this technique. -Read about it more in the [HttpClient guide](guide/http#security-xsrf-protection). +Read about it more in the [HttpClient guide](guide/http-security-xsrf-protection). For information about CSRF at the Open Web Application Security Project \(OWASP\), see [Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) and [Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html). The Stanford University paper [Robust Defenses for Cross-Site Request Forgery](https://seclab.stanford.edu/websec/csrf/csrf.pdf) is a rich source of detail. diff --git a/aio-ja/content/guide/security.md b/aio-ja/content/guide/security.md index 6c65483fb5..b576e3ef15 100644 --- a/aio-ja/content/guide/security.md +++ b/aio-ja/content/guide/security.md @@ -13,7 +13,7 @@ Angularでの対応について説明します。認証や認可などアプリ
脆弱性の報告
-Angular is part of Google [Open Source Software Vulnerability Reward Program](https://bughunters.google.com/about/rules/6521337925468160/google-open-source-software-vulnerability-reward-program-rules), for vulnerabilities in Angular please submit your report [here](https://bughunters.google.com/report). +AngularはGoogleの [Open Source Software Vulnerability Reward Program](https://bughunters.google.com/about/rules/6521337925468160/google-open-source-software-vulnerability-reward-program-rules)の対象です。[Angularの脆弱性については、https://bughunters.google.com からレポートを提出してください](https://bughunters.google.com/report)。 セキュリティに関する問題を Google がどのように扱うかは[Google's security philosophy](https://www.google.com/about/appsecurity/) を参照してください。 @@ -341,7 +341,7 @@ Cookieが設定されているWebサイトのコードだけが、そのサイ つまり、アプリケーションだけがこのCookieトークンを読み取り、カスタムヘッダーを設定できます。 `evil.com`の悪意のあるコードにはできません。 -Angular の `HttpClient` モジュールはこれらのクライアント側の処理をサポートしています。詳しくは [HttpClient guide](/guide/http#security-xsrf-protection) の章を参照してください。 +Angular の `HttpClient` モジュールはこれらのクライアント側の処理をサポートしています。詳しくは [HttpClientガイド](/guide/http-security-xsrf-protection) の章を参照してください。 CSRFについてはオープンWebアプリケーションセキュリティプロジェクト(OWASP)の、 [Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) および diff --git a/aio-ja/content/guide/signals.en.md b/aio-ja/content/guide/signals.en.md index afac47ca4b..fe454794db 100644 --- a/aio-ja/content/guide/signals.en.md +++ b/aio-ja/content/guide/signals.en.md @@ -65,7 +65,7 @@ const doubleCount: Signal = computed(() => count() * 2); The `doubleCount` signal depends on `count`. Whenever `count` updates, Angular knows that anything which depends on either `count` or `doubleCount` needs to update as well. -#### Computeds are both lazily evaluated and memoized +#### Computed signals are both lazily evaluated and memoized `doubleCount`'s derivation function does not run to calculate its value until the first time `doubleCount` is read. Once calculated, this value is cached, and future reads of `doubleCount` will return the cached value without recalculating. @@ -123,7 +123,7 @@ Effects always run **at least once.** When an effect runs, it tracks any signal Effects always execute **asynchronously**, during the change detection process. -### Uses for effects +### Use cases for effects Effects are rarely needed in most application code, but may be useful in specific circumstances. Here are some examples of situations where an `effect` might be a good solution: @@ -140,7 +140,7 @@ Because of these risks, setting signals is disallowed by default in effects, but ### Injection context -By default, registering a new effect with the `effect()` function requires an "injection context" (access to the `inject` function). The easiest way to provide this is to call `effect` within a component, directive, or service `constructor`: +By default, registering a new effect with the `effect()` function requires an [injection context](/guide/dependency-injection-context) (access to the `inject` function). The easiest way to provide this is to call `effect` within a component, directive, or service `constructor`: ```ts @Component({...}) @@ -263,3 +263,5 @@ effect((onCleanup) => { }); }); ``` + +@reviewed 2023-06-21 diff --git a/aio-ja/content/guide/signals.md b/aio-ja/content/guide/signals.md index d961529ad9..e83ad19b2f 100644 --- a/aio-ja/content/guide/signals.md +++ b/aio-ja/content/guide/signals.md @@ -123,7 +123,7 @@ Effectは**少なくとも1回は**必ず実行される。Effect が実行さ Effectは常に**非同期的**に、変更検知のプロセス中に実行されます。 -### Effectの用途 +### Effectのユースケース Effect は、大部分のアプリケーションコードではほとんど必要とされませんが、特定の状況下では役に立つことがあります。以下は、`effect`がよい解決策となるような状況の例です: @@ -140,7 +140,7 @@ Effect は、大部分のアプリケーションコードではほとんど必 ### インジェクションコンテキスト -デフォルトでは、`effect()`関数で新しいエフェクトを登録するには、「インジェクションコンテキスト」(`inject`関数へのアクセス)が必要です。これを提供するもっとも簡単な方法は、コンポーネント、ディレクティブ、またはサービスの `constructor` の中で `effect` を呼び出すことです: +デフォルトでは、`effect()`関数で新しいエフェクトを登録するには、「[インジェクションコンテキスト](/guide/dependency-injection-context)」(`inject`関数へのアクセス)が必要です。これを提供するもっとも簡単な方法は、コンポーネント、ディレクティブ、またはサービスの `constructor` の中で `effect` を呼び出すことです: ```ts @Component({...}) @@ -263,3 +263,5 @@ effect((onCleanup) => { }); }); ``` + +@reviewed 2023-06-21 diff --git a/aio-ja/content/guide/standalone-components.en.md b/aio-ja/content/guide/standalone-components.en.md index 6909a380b7..7fba5c5f6f 100644 --- a/aio-ja/content/guide/standalone-components.en.md +++ b/aio-ja/content/guide/standalone-components.en.md @@ -273,7 +273,7 @@ bootstrapApplication(PhotoAppComponent, { }); ``` -The new bootstrap API gives us back the means of configuring “module injectors” without using `NgModule`s. In this sense, the “module” part of the name is no longer relevant and we’ve decided to introduce a new term: “environment injectors”. +The new bootstrap API gives us back the means of configuring “module injectors” without using `NgModule`s. In this sense, the “module” part of the name is no longer relevant, and we’ve decided to introduce a new term: “environment injectors”. Environment injectors can be configured using one of the following: @@ -320,7 +320,7 @@ class DatePickerComponent { @NgModule({         declarations: [DatePickerComponent], -        exports: [DatePickerComponent] +        exports: [DatePickerComponent],         providers: [CalendarService], }) class DatePickerModule { @@ -338,7 +338,7 @@ class DateModalComponent { In the above example, the component `DateModalComponent` is standalone - it can be consumed directly and has no NgModule which needs to be imported in order to use it. However, `DateModalComponent` has a dependency, the `DatePickerComponent,` which is imported via its NgModule (the `DatePickerModule`). This NgModule may declare providers (in this case: `CalendarService`) which are required for the `DatePickerComponent` to function correctly. -When Angular creates a standalone component, it needs to know that the current injector has all of the necessary services for the standalone component's dependencies, including those based on NgModules. To guarantee that, in some cases Angular will create a new "standalone injector" as a child of the current environment injector. Today, this happens for all bootstrapped standalone components: it will be a child of the root environment injector. The same rule applies to the dynamically created (for example, by the router or the `ViewContainerRef` API) standalone components. +When Angular creates a standalone component, it needs to know that the current injector has all the necessary services for the standalone component's dependencies, including those based on NgModules. To guarantee that, in some cases Angular will create a new "standalone injector" as a child of the current environment injector. Today, this happens for all bootstrapped standalone components: it will be a child of the root environment injector. The same rule applies to the dynamically created (for example, by the router or the `ViewContainerRef` API) standalone components. A separate standalone injector is created to ensure that providers imported by a standalone component are “isolated” from the rest of the application. This lets us think of standalone components as truly self-contained pieces that can’t “leak” their implementation details to the rest of the application. diff --git a/aio-ja/content/guide/standalone-components.md b/aio-ja/content/guide/standalone-components.md index d974823f15..10577221b0 100644 --- a/aio-ja/content/guide/standalone-components.md +++ b/aio-ja/content/guide/standalone-components.md @@ -321,7 +321,7 @@ class DatePickerComponent { @NgModule({         declarations: [DatePickerComponent], -        exports: [DatePickerComponent] +        exports: [DatePickerComponent],         providers: [CalendarService], }) class DatePickerModule { diff --git a/aio-ja/content/guide/testing-components-scenarios.en.md b/aio-ja/content/guide/testing-components-scenarios.en.md index 192398a9fe..19e30798c5 100644 --- a/aio-ja/content/guide/testing-components-scenarios.en.md +++ b/aio-ja/content/guide/testing-components-scenarios.en.md @@ -605,7 +605,7 @@ Each symbol \(`-`, `x`, `|`, `#`\) marks the passing of one frame. A *cold* observable doesn't produce values until you subscribe to it. Most of your application observables are cold. -All [*HttpClient*](guide/http) methods return cold observables. +All [*HttpClient*](guide/understanding-communicating-with-http) methods return cold observables. A *hot* observable is already producing values *before* you subscribe to it. The [`Router.events`](api/router/Router#events) observable, which reports router activity, is a *hot* observable. diff --git a/aio-ja/content/guide/testing-components-scenarios.md b/aio-ja/content/guide/testing-components-scenarios.md index 8559838b83..731bd67e1b 100644 --- a/aio-ja/content/guide/testing-components-scenarios.md +++ b/aio-ja/content/guide/testing-components-scenarios.md @@ -733,7 +733,7 @@ _マーブルフレーム_とは、テスト時間の仮想的な単位です。 {@a cold-observable} _コールド_ Observableはサブスクライブされるまで値を発行しません。 アプリケーションのObservableのほとんどはコールドです。 -すべての[_HttpClient_](guide/http)メソッドはコールドObservableを返します。 +すべての[_HttpClient_](guide/understanding-communicating-with-http)メソッドはコールドObservableを返します。 _ホット_ Observableは購読する_前_にすでに値を発行しています。 ルーターアクティビティを報告する[_Router.events_](api/router/Router#events)Observable、 diff --git a/aio-ja/content/guide/testing-services.en.md b/aio-ja/content/guide/testing-services.en.md index f5389e2a0d..852ea6f860 100644 --- a/aio-ja/content/guide/testing-services.en.md +++ b/aio-ja/content/guide/testing-services.en.md @@ -129,7 +129,7 @@ Although this testing guide follows the traditional style and the default [CLI s ## Testing HTTP services -Data services that make HTTP calls to remote servers typically inject and delegate to the Angular [`HttpClient`](guide/http) service for XHR calls. +Data services that make HTTP calls to remote servers typically inject and delegate to the Angular [`HttpClient`](guide/http-test-requests) service for XHR calls. You can test a data service with an injected `HttpClient` spy as you would test any service with a dependency. @@ -152,7 +152,7 @@ Extended interactions between a data service and the `HttpClient` can be complex The `HttpClientTestingModule` can make these testing scenarios more manageable. -While the *code sample* accompanying this guide demonstrates `HttpClientTestingModule`, this page defers to the [Http guide](guide/http#testing-http-requests), which covers testing with the `HttpClientTestingModule` in detail. +While the *code sample* accompanying this guide demonstrates `HttpClientTestingModule`, this page defers to the [Http guide](guide/http-test-requests), which covers testing with the `HttpClientTestingModule` in detail. diff --git a/aio-ja/content/guide/testing-services.md b/aio-ja/content/guide/testing-services.md index d05b8b7fc8..52c41a137d 100644 --- a/aio-ja/content/guide/testing-services.md +++ b/aio-ja/content/guide/testing-services.md @@ -170,7 +170,7 @@ _この代替アプローチ_を自身のプロジェクト内で採用するこ #### HTTPサービスをテストする リモートサーバーに対してHTTP呼び出しをするデータサービスは、通常、 -XHR呼び出しのためのAngularの[`HttpClient`](guide/http)サービスを注入して委譲します。 +XHR呼び出しのためのAngularの[`HttpClient`](guide/http-test-requests)サービスを注入して委譲します。 依存関係をもつ任意のサービスをテストするために、注入された`HttpClient`のスパイを使用して データサービスのテストができます。 @@ -201,4 +201,12 @@ Observableを_サブスクライブ_する必要があります。 このガイドに付属する_コードサンプル_では`HttpClientTestingModule`のデモをしますが、 このページでは`HttpClientTestingModule`を使用したテストの詳細をカバーをしている -[Httpガイド](guide/http#testing-http-requests)に先送りします。 +[Httpガイド](guide/http-test-requests)に先送りします。 + + + + + + + +@reviewed 2022-02-28 diff --git a/aio-ja/content/guide/universal.en.md b/aio-ja/content/guide/universal.en.md index 358081d19b..29cd2b943a 100644 --- a/aio-ja/content/guide/universal.en.md +++ b/aio-ja/content/guide/universal.en.md @@ -2,13 +2,13 @@ This guide describes **Angular Universal**, a technology that allows Angular to render applications on the server. -By default, Angular renders applications only in a *browser*. Angular Universal allows Angular to render an application on the *server*, generating *static* HTML contents, which represents an application state. Once the HTML contents is rendered in a browser, Angular bootstraps an application and reuses the information available in the server-generated HTML. +By default, Angular renders applications only in a *browser*. Angular Universal allows Angular to render an application on the *server*, generating *static* HTML content, which represents an application state. Once the HTML content is rendered in a browser, Angular bootstraps an application and reuses the information available in the server-generated HTML. -With server-side rendering an application generally renders in a browser faster, giving users a chance to view the application UI before it becomes fully interactive. See ([the "Why use Server-Side Rendering?" section](#why-do-it)) below for addition information. +With server-side rendering an application generally renders in a browser faster, giving users a chance to view the application UI before it becomes fully interactive. See the ["Why use Server-Side Rendering?"](#why-do-it) section below for additional information. Also for a more detailed look at different techniques and concepts surrounding SSR, check out this [article](https://developers.google.com/web/updates/2019/02/rendering-on-the-web). -You can enable server-side rendering in your Angular application using the `@nguniversal/express-engine` schematic as described below. +You can enable server-side rendering in your Angular application using the `@nguniversal/express-engine` package as described below.
@@ -66,10 +66,10 @@ The command updates the application code to enable SSR and adds extra files to t
- app.config.ts                   // < client-side application configuration (standalone app only) + app.config.ts                   // <-- client-side application configuration (standalone app only)
- app.module.ts                 // < client-side application module (NgModule app only) + app.module.ts                 // <-- client-side application module (NgModule app only)
@@ -226,9 +226,9 @@ Universal applications use the Angular `platform-server` package \(as opposed to server implementations of the DOM, `XMLHttpRequest`, and other low-level features that don't rely on a browser. The server \([Node.js Express](https://expressjs.com) in this guide's example\) passes client requests for application pages to the NgUniversal `ngExpressEngine`. -Under the hood, the render functions, while providing caching and other helpful utilities. +Under the hood, the engine renders the app, while also providing caching and other helpful utilities. -The render functions takes as inputs a *template* HTML page \(usually `index.html`\), and Angular *module* containing components or a function that when invoked returns a `Promise` that resolves to an `ApplicationRef`, and a *route* that determines which components to display. The route comes from the client's request to the server. +The render function takes as inputs a *template* HTML page \(usually `index.html`\), and an Angular *module* containing components. Alternatively, it can take a function that when invoked returns a `Promise` that resolves to an `ApplicationRef`, and a *route* that determines which components to display. The route comes from the client's request to the server. Each request results in the appropriate view for the requested route. The render function renders the view within the `` tag of the template, creating a finished HTML page for the client. @@ -279,8 +279,8 @@ This engine's `Promise` callback returns the rendered page to the web server, wh
**NOTE**:
-The basic behavior described below is handled automatically when using the NgUniversal Express schematic. -This is helpful when trying to understand the underlying behavior or replicate it without using the schematic. +The basic behavior described below is handled automatically when using the NgUniversal Express package. +This is helpful when trying to understand the underlying behavior or replicate it without using the package.
@@ -298,12 +298,12 @@ Because you use routing, you can recognize the three types of requests and handl | Routing request types | Details | |:--- |:--- | -| Data request | Request URL that begins `/api`. | -| App navigation | Request URL with no file extension. | -| Static asset | All other requests. | +| Data request | Request URL that begins `/api` | +| App navigation | Request URL with no file extension | +| Static asset | All other requests | A Node.js Express server is a pipeline of middleware that filters and processes requests one after the other. -You configure the Node.js Express server pipeline with calls to `server.get()` like this one for data requests. +You configure the Node.js Express server pipeline with calls to `server.get()` like this one for data requests: @@ -317,7 +317,7 @@ In practice, you would remove that module and register your web API middleware o
-The following code filters for request URLs with no extensions and treats them as navigation requests. +The following code filters for request URLs with no extensions and treats them as navigation requests: @@ -357,7 +357,7 @@ Now, on every HTTP request made as part of rendering the application on the serv |:--- |:--- | | npm run dev:ssr | Similar to [`ng serve`](cli/serve), which offers live reload during development, but uses server-side rendering. The application runs in watch mode and refreshes the browser after every change. This command is slower than the actual `ng serve` command. | | ng build && ng run app-name:server | Builds both the server script and the application in production mode. Use this command when you want to build the project for deployment. | -| npm run serve:ssr | Starts the server script for serving the application locally with server-side rendering. It uses the build artifacts created by `ng run build:ssr`, so make sure you have run that command as well.
**NOTE**:
`serve:ssr` is not intended to be used to serve your application in production, but only for testing the server-side rendered application locally.
| +| npm run serve:ssr | Starts the server script for serving the application locally with server-side rendering. It uses the build artifacts created by `npm run build:ssr`, so make sure you have run that command as well.
**NOTE**:
`serve:ssr` is not intended to be used to serve your application in production, but only for testing the server-side rendered application locally.
| | npm run prerender | Used to prerender an application's pages. Read more about prerendering [here](guide/prerendering). | @@ -366,4 +366,4 @@ Now, on every HTTP request made as part of rendering the application on the serv -@reviewed 2023-04-25 +@reviewed 2023-06-21 diff --git a/aio-ja/content/guide/universal.md b/aio-ja/content/guide/universal.md index f0e31afb82..1a4232815d 100644 --- a/aio-ja/content/guide/universal.md +++ b/aio-ja/content/guide/universal.md @@ -8,7 +8,7 @@ また、SSRをめぐるさまざまなテクニックやコンセプトについては、こちらの[記事](https://developers.google.com/web/updates/2019/02/rendering-on-the-web)をご覧ください。 -次のように、`@nguniversal/express-engine` schematicsを使用して、Angularアプリケーションでサーバーサイドレンダリングを有効にすることができます。 +次のように、`@nguniversal/express-engine` パッケージを使用して、Angularアプリケーションでサーバーサイドレンダリングを有効にすることができます。
@@ -66,10 +66,10 @@ The command updates the application code to enable SSR and adds extra files to t
- app.config.ts                   // < client-side application configuration (standalone app only) + app.config.ts                   // <-- client-side application configuration (standalone app only)
- app.module.ts                 // < client-side application module (NgModule app only) + app.module.ts                 // <-- client-side application module (NgModule app only)
@@ -226,9 +226,9 @@ Universal Web サーバーは、[Universal テンプレートエンジン](#univ これは、DOM、`XMLHttpRequest`、およびブラウザに依存しないその他の低レベル機能のサーバー実装を提供します。 サーバー (このガイドの例では [Node.js Express](https://expressjs.com/)) は、アプリケーションページのクライアントリクエストを NgUniversal の `ngExpressEngine` に渡します。 -Under the hood, the render functions, while providing caching and other helpful utilities. +裏側では、このエンジンがアプリケーションをレンダリングし、キャッシュやその他の便利なユーティリティも提供します。 -The render functions takes as inputs a *template* HTML page \(usually `index.html`\), and Angular *module* containing components or a function that when invoked returns a `Promise` that resolves to an `ApplicationRef`, and a *route* that determines which components to display. The route comes from the client's request to the server. +render関数は、*テンプレート*となるHTMLページ(通常は`index.html`)と、コンポーネントを含むAngularの*モジュール*を入力として受け取ります。あるいは、呼び出されたときに `ApplicationRef` に解決される`Promise`を返す関数と、どのコンポーネントを表示するかを決定する*ルート*を受け取ることもできます。ルートはクライアントからサーバーへのリクエストに基づきます。 各リクエストの結果、リクエストされたルートの適切なビューが表示されます。 render 関数は、テンプレートの `` タグ内でビューをレンダリングし、 @@ -278,8 +278,13 @@ The `ngExpressEngine()` function is a wrapper around the Angular `platform-serve ### リクエスト URL のフィルタリング -メモ: NgUniversal Express schematic を使用すると、次に説明する基本的な動作が自動的に処理されます。 -これは、基本的な動作を理解したり、schematic を使用せずに複製したりするときに役立ちます。 +
+ +**NOTE**:
+メモ: NgUniversal Expressパッケージを使用すると、次に説明する基本的な動作が自動的に処理されます。 +これは、基本的な動作を理解したり、パッケージを使用せずに複製したりするときに役立ちます。 + +
Web サーバーは、_アプリのページのリクエスト_ を他の種類のリクエストと区別する必要があります。 @@ -355,7 +360,7 @@ Now, on every HTTP request made as part of rendering the app on the server, Angu |:--- |:--- | | npm run dev:ssr | Similar to [`ng serve`](cli/serve), which offers live reload during development, but uses server-side rendering. The application runs in watch mode and refreshes the browser after every change. This command is slower than the actual `ng serve` command. | | ng build && ng run app-name:server | Builds both the server script and the application in production mode. Use this command when you want to build the project for deployment. | -| npm run serve:ssr | Starts the server script for serving the application locally with server-side rendering. It uses the build artifacts created by `ng run build:ssr`, so make sure you have run that command as well.
**NOTE**:
`serve:ssr` is not intended to be used to serve your application in production, but only for testing the server-side rendered application locally.
| +| npm run serve:ssr | Starts the server script for serving the application locally with server-side rendering. It uses the build artifacts created by `npm run build:ssr`, so make sure you have run that command as well.
**NOTE**:
`serve:ssr` is not intended to be used to serve your application in production, but only for testing the server-side rendered application locally.
| | npm run prerender | Used to prerender an application's pages. Read more about prerendering [here](guide/prerendering). | @@ -364,4 +369,4 @@ Now, on every HTTP request made as part of rendering the app on the server, Angu -@reviewed 2023-04-25 +@reviewed 2023-06-21 \ No newline at end of file diff --git a/aio-ja/content/guide/what-is-angular.en.md b/aio-ja/content/guide/what-is-angular.en.md index 5a1861da40..acec418222 100644 --- a/aio-ja/content/guide/what-is-angular.en.md +++ b/aio-ja/content/guide/what-is-angular.en.md @@ -190,7 +190,7 @@ Some of the libraries available to you include: |:--- |:--- | | [Angular Router](guide/router) | Advanced client-side navigation and routing based on Angular components. Supports lazy-loading, nested routes, custom path matching, and more. | | [Angular Forms](guide/forms-overview) | Uniform system for form participation and validation. | -| [Angular HttpClient](guide/http) | Robust HTTP client that can power more advanced client-server communication. | +| [Angular HttpClient](guide/understanding-communicating-with-http) | Robust HTTP client that can power more advanced client-server communication. | | [Angular Animations](guide/animations) | Rich system for driving animations based on application state. | | [Angular PWA](guide/service-worker-intro) | Tools for building Progressive Web Applications \(PWA\) including a service worker and Web application manifest. | | [Angular Schematics](guide/schematics) | Automated scaffolding, refactoring, and update tools that simplify development at large scale. | diff --git a/aio-ja/content/guide/what-is-angular.md b/aio-ja/content/guide/what-is-angular.md index 3d4a2d4262..2aa7b46fac 100644 --- a/aio-ja/content/guide/what-is-angular.md +++ b/aio-ja/content/guide/what-is-angular.md @@ -172,7 +172,7 @@ Angular CLIの詳細については、[Angular CLIリファレンス](/cli)セ |:--- |:--- | | [Angular Router](guide/router) | Angularコンポーネントに基づく高度なクライアント側のナビゲーションとルーティング。遅延読み込み、ネストされたルート、カスタムパスマッチングなどをサポートします。 | | [Angular Forms](guide/forms-overview) | フォームへの介入と検証のための統一されたシステム。 | -| [Angular HttpClient](guide/http) | より高度なクライアント/サーバー通信を強化できる堅牢なHTTPクライアント。 | +| [Angular HttpClient](guide/understanding-communicating-with-http) | より高度なクライアント/サーバー通信を強化できる堅牢なHTTPクライアント。 | | [Angular Animations](guide/animations) | アプリケーションの状態に基づいてアニメーションを駆動するリッチなシステム。 | | [Angular PWA](guide/service-worker-intro) | Service WorkerやWebアプリケーションマニフェストを含むプログレッシブWebアプリケーション(PWA)を構築するためのツール。 | | [Angular Schematics](guide/schematics) | A大規模な開発を簡素化する自動化されたスキャフォールディング、リファクタリング、および更新ツール。 | diff --git a/aio-ja/content/guide/workspace-config.en.md b/aio-ja/content/guide/workspace-config.en.md index 673f2ae16d..80c8f67d6b 100644 --- a/aio-ja/content/guide/workspace-config.en.md +++ b/aio-ja/content/guide/workspace-config.en.md @@ -235,15 +235,15 @@ For details of those options and their possible values, see the [Angular CLI Ref Some extra options can only be set through the configuration file, either by direct editing or with the [`ng config`](cli/config) command. -| Options properties | Details | -|:--- |:--- | -| `assets` | An object containing paths to static assets to add to the global context of the project. The default paths point to the project's icon file and its `assets` directory. See more in the [Assets configuration](#asset-config) section. | -| `styles` | An array of style files to add to the global context of the project. Angular CLI supports CSS imports and all major CSS preprocessors: [sass/scss](https://sass-lang.com) and [less](http://lesscss.org). See more in the [Styles and scripts configuration](#style-script-config) section. | +| Options properties | Details | +|:--- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `assets` | An object containing paths to static assets to add to the global context of the project. The default paths point to the project's icon file and its `assets` directory. See more in the [Assets configuration](#asset-config) section. | +| `styles` | An array of style files to add to the global context of the project. Angular CLI supports CSS imports and all major CSS preprocessors: [sass/scss](https://sass-lang.com) and [less](https://lesscss.org). See more in the [Styles and scripts configuration](#style-script-config) section. | | `stylePreprocessorOptions` | An object containing option-value pairs to pass to style preprocessors. See more in the [Styles and scripts configuration](#style-script-config) section. | | `scripts` | An object containing JavaScript script files to add to the global context of the project. The scripts are loaded exactly as if you had added them in a `