-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
# Asynchronous | ||
|
||
RESTer 支援非同步發送 request 。 RESTer 提供*全域設定*、*單點設定*和*群組設定*三種客製化方法來打造 client。 | ||
|
||
## Concept | ||
|
||
RESTer 是如何決定呼叫行為? | ||
|
||
[`ResterClientTrait`](/src/Plugins/ResterClientTrait.php) 有一個 protected method 為 `isAsynchronousCall()` 。它決定了 RESTer 將會用什麼樣的行為來呼叫 API 。順序如下: | ||
|
||
1. 如果 API 能設定非同步呼叫,且為非同步,則會使用非同步呼叫 | ||
2. 如果 Client 能設定非同步呼叫,且為非同步,則會使用非同步呼叫 | ||
3. 如果以上皆非,則會使用同步呼叫 | ||
|
||
### Traits | ||
|
||
預設 `ResterClientTrait` 是無法設定非同步呼叫的,因此上面的判斷結果會是*以上皆非*的同步呼叫。如果有需要,可以掛上對應的 Trait 即可有不同的行為,可以掛的 Trait 如下: | ||
|
||
* `\Corp104\Rester\Plugins\SynchronousTrait` - 同步呼叫 | ||
* `\Corp104\Rester\Plugins\AsynchronousTrait` - 非同步呼叫 | ||
* `\Corp104\Rester\Support\SynchronousNullTrait` - 執行階段決定 | ||
|
||
只要有掛上面幾個 trait 的話,都會有下面三種設定方法: | ||
|
||
* `synchronous()` - 設定成同步呼叫 | ||
* `asynchronous()` - 設定成非同步呼叫 | ||
* `setSynchronous($value)` - 直接指定是否為同步呼叫,也可以指定 `null` | ||
|
||
### Default trait | ||
|
||
RESTer 的世界裡,有四種預設物件會掛 `SynchronousNullTrait` : | ||
|
||
* Api - `SynchronousNullTrait` | ||
* Collection - `SynchronousNullTrait` | ||
* Mapping - `SynchronousNullTrait` | ||
* ResterClient - `SynchronousNullTrait` | ||
|
||
這幾個物件都可以由開發者自行設定;如果都沒設定的話,將會採同步呼叫。 | ||
|
||
## 全域設定 | ||
|
||
了解概念之後,就會知道什麼是*全域設定*了。 | ||
|
||
比方說 Client 物件設定 `asynchronous()` 後,而 API 預設值會是 `null` (執行階段決定),這樣就會以 Client 設定為主,結果就會是非同步呼叫;反之亦然。 | ||
|
||
這樣的設定方法也就是全域設定。 | ||
|
||
`ResterClient` 範例如下: | ||
|
||
```php | ||
$resterClient = new ResterClient(); | ||
$resterClient->asynchronous(); | ||
|
||
// 設定 API ... | ||
|
||
// 非同步呼叫 | ||
$resterClient->foo(); | ||
``` | ||
|
||
`ResterClientTrait` 範例如下: | ||
|
||
```php | ||
class MyClient | ||
{ | ||
use ResterClientTrait; | ||
use ResterMagicTrait; | ||
use AsynchronousTrait; | ||
|
||
// ... | ||
} | ||
|
||
$myClient = new MyClient(); | ||
|
||
// 非同步呼叫 | ||
$myClient->foo(); | ||
``` | ||
|
||
## 單點設定 | ||
|
||
*單點設定*指的是 API 自己本身的設定。實際範例如下: | ||
|
||
```php | ||
$resterClient = new ResterClient(); | ||
|
||
// 設定全域的同步呼叫 | ||
$resterClient->synchronous(); | ||
$resterClient->provisionMapping([ | ||
'foo' => new Endpoint('GET', '/foo'), | ||
'fooAsync' => Endpoint::create('GET', '/fooAsync')->asynchronous(), | ||
]); | ||
|
||
// 同步呼叫 | ||
$resterClient->foo(); | ||
|
||
// 非同步呼叫 | ||
$resterClient->fooAsync(); | ||
``` | ||
|
||
實作 `ApiInterface` 的範例: | ||
|
||
```php | ||
class MyApi implements ApiInterface | ||
{ | ||
use AsynchronousTrait; | ||
|
||
// ... | ||
} | ||
|
||
$resterClient->provisionMapping([ | ||
'foo' => new MyApi(), | ||
]); | ||
|
||
// 非同步呼叫 | ||
$resterClient->foo(); | ||
``` | ||
|
||
## 群組設定 | ||
|
||
在 RESTer 的世界裡,有兩個類別具有群組的特性: Client 群組的 `Collection` 與 Api 群組的 `Mapping` 。 | ||
|
||
簡而言之,全域設定與單點設定是屬於在執行階段**判斷**要採用什麼行為呼叫 API ,而群組設定則會在執行階段**設定** Client 物件(全域設定)或 Api 物件(單點設定)或。此邏輯寫在 `\Corp104\Rester\Support\SynchronousAwareTrait` 的 `transferSynchronousStatusTo()` 裡。會經過以下多個判斷,才會進行設定: | ||
|
||
1. 被設定的物件需繼承 `SynchronousAwareInterface` | ||
2. 群組物件必須設定過才行(`asynchronous()` 或 `synchronous()`) | ||
3. Client 物件或 Api 物件必須是 `null` (執行階段決定) | ||
|
||
舉一個 Mapping 範例: | ||
|
||
```php | ||
$mapping = new Mapping(); | ||
$mapping->asynchronous(); | ||
|
||
// 這個 Api 將會是非同步呼叫(三個條件皆達成) | ||
$mapping->set('fooAsync', new Api('GET', '/fooAsync')); | ||
|
||
// 這個 Api 將會是同步呼叫(第三個條件未達成) | ||
$mapping->set('fooSync', Api::create('GET', '/fooSync')->synchronous()); | ||
``` |