---
agentTools:
  projectIndex: https://developers.pipefy.com/llms.txt
---

# Promises

How asynchronous results are returned

**Every function on the client is asynchronous.** `p.card()`, `p.fields()`, `p.query()`, `p.get()` and the rest all return a promise. Your app runs in an iframe, so every call crosses the frame boundary — even reads of context Pipefy already has, like [`p.timezone()`](https://developers.pipefy.com/docs/get-pipefy-data#ptimezone), come back asynchronously.

There is nothing Pipefy-specific to learn here — use `.then()`/`.catch()`/`.finally()`, or `async`/`await`:

```javascript
// then / catch
p.card()
  .then(function (card) {
    console.log(card.title);
  })
  .catch(function (error) {
    console.error('Could not load the card', error);
  });

// async / await
async function showCardTitle() {
  try {
    const card = await p.card();
    console.log(card.title);
  } catch (error) {
    console.error('Could not load the card', error);
  }
}
```

## Always handle rejection

Your app runs in an iframe inside Pipefy, so an unhandled rejection is invisible to the user — nothing appears, and nothing explains why. Attach a `.catch()` (or use `try`/`catch`) and tell the user what happened with [`p.showNotification()`](https://developers.pipefy.com/docs/user-interface-functions#pshownotificationtext-type):

```javascript
p.get('pipe', 'private', 'token')
  .then(function (token) {
    if (!token) {
      return showConnectPrompt();
    }
    return loadData(token);
  })
  .catch(function (error) {
    console.error(error);
    p.showNotification('Could not reach the server. Please try again.', 'error');
  });
```

## Running calls in parallel

Independent reads should not wait on each other:

```javascript
Promise.all([p.card(), p.fields(), p.pipe()]).then(function (results) {
  const [card, fields, pipe] = results;
  render(card, fields, pipe);
});
```

## The synchronous exceptions

Only the client's **plain properties** are synchronous, because they are data rather than functions: `p.locale`, `p.appId`, `p.pipeId`, `p.cardId` and the rest of the [context properties](https://developers.pipefy.com/docs/get-pipefy-data#context-properties).

Anything you *call* is asynchronous. If it has parentheses, it returns a promise.

## Not a native `Promise`

The returned object is promise-*like*, not a native [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). It implements `.then()`, `.catch()` and `.finally()`, and works with `await` and `Promise.all()`, so in practice you can treat it as one. The single difference worth knowing:

```javascript
p.card() instanceof Promise; // false — use await or .then(), don't type-check it
```

To get a real native promise, wrap it: `Promise.resolve(p.card())`.

## PipefyApp.Promise

> ⚠️ Deprecated
>
> `PipefyApp.Promise` is an alias for the browser's native `Promise`. It exists only so that older apps referencing it keep working, and will be removed in a future major version. Use `Promise` directly.

Older versions of this page said the SDK shipped Bluebird. It no longer does — native promises are supported everywhere Pipefy runs, so the polyfill was dropped:

```javascript
// Don't do this
var Promise = PipefyApp.Promise;

// Just use the global
new Promise(function (resolve) { /* ... */ });
```