# Invoke

## Action

`action`最後的結果最由最後的參數(callback)呈現，第一個參數是錯誤，第二個參數為運算結果。

如果你的程式是同步的，那Action是完全同步的，但仍建議把全部的函式視為非同步。

{% hint style="info" %}
在某些狀況下第一個參數不會是`error`，詳情請參照[`noGood`](/the-instance/invoke.md#nogood)。
{% endhint %}

```javascript
packhouse.tool('math/sum').action(10, 20, (error, result) => {
    console.log(result) // 30
})
```

## Promise

如果使用Promise，則回傳Promise物件。

{% hint style="info" %}
在某些狀況下不會觸發`catch`，詳情請參照[`noGood`](/the-instance/invoke.md#nogood)。
{% endhint %}

```javascript
packhouse.tool('math/sum').promise(10, 20).then(result => {
    console.log(result) // 30
})
```

## Per Invoke

在執行Invoke前可以註冊一些行為。

### Pack

參數預處理，你可以在宣告之前先注入參數：

```javascript
packhouse
    .tool('math/sum')
    .pack(10)
    .action(10, (error, result) => {
        console.log(result) // 20
    })
```

#### In Include

在Install中引用`tool`時只要給予額外的參數也可以運行`pack`：

```javascript
const tool = {
    install({ include }) {
        include('sum').tool('sum', 10)
    }
}
```

在Include中引用`line`的後續參數也有`pack`的功能：

```javascript
const tool = {
    install({ include }) {
        include('math').line('math', 10)
    },
    handler(self) {
        self.line('math')()
            .action((error, result) => {
                console.log(result) // 10
            })
    }
}
```

### No Good

當錯誤處理時，由`noGood`接收。

{% hint style="info" %}
非監聽制，反覆宣告會覆蓋上一次的宣告。
{% endhint %}

#### Action

當宣告`noGood`後`action`的第一個參數會被移除。

```javascript
packhouse
    .tool('math/sum')
    .noGood(e => console.log(e))
    .action('1', '2', result => {
        // 這裡不工作
    })
```

#### Promise

當宣告`noGood`後`promise`不會被`reject`。

> 嚴格來說如果你使用的是Promise請使用`reject`而不是noGood

```javascript
packhouse
    .tool('math/sum')
    .noGood(e => console.log(e))
    .promise('1', '2')
    .then(() => {
        // 這裡會執行
    })
```

你可以運用第二個參數來強行宣告為`reject`。

```javascript
packhouse
    .tool('math/sum')
    .noGood(e => console.log(e), { reject: true })
    .promise('1', '2')
    .then(() => {
        // 這裡不會執行
    })
    .catch(() => {
        // 這裡會執行
    })
```

### Always

無論如何都會執行，事件發生在Action之後。

{% hint style="info" %}
非監聽制，反覆宣告會覆蓋上一次的宣告。
{% endhint %}

```javascript
packhouse
    .tool('math/sum')
    .always(({ result, success, context }) => {
        console.log(result) // 30
        console.log(success) // true
        console.log(context.id) // uuid, 每次執行都會配發一個新的id
        console.log(context.caller) // 如果該次呼叫是由另一個tool調用，可以得知是哪個id呼叫
    })
    .promise(10 , 20)
```

#### Promise

運行Promise時請使用`finally`而不是`alawys`。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://packhouse-doc.metalsheep.com/the-instance/invoke.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
