Skip to content

Subscribe EVENT

You can use RxNostr's use() method to subscribe EVENT messages.

As you can see with the specific code in Getting Started, the general flow of the EVENT message subscription is as follows:

  1. Create a RxNostr object by createRxNostr().
  2. Create a RxReq object by createRxForwardReq() or createRxBackwardReq().
  3. Do rxNostr.use(rxReq).subscribe(callback) to register a listener and get a Subscription object as the return value.
  4. Emit REQ messages by rxReq.emit(filter).
  5. When you are done with what you need to do, do subscription.unsubscribe() to finish the subscription.

The important point here is whether to choose createRxForwardReq() or createRxBackwardReq() in step 2. The RxReq created by createRxForwardReq() follows the Forward Strategy and the RxReq created by createRxBackwardReq() follows the Backward Strategy.

Briefly speaking, the difference between the two is whether the events to be fetched is future events or past events. If you want to get both past and future events, tune a query in the Forward Strategy or separate it into the Forward Strategy and Backward Strategy.

Note

To avoid confusion between Subscription as defined in NIP-01 and Subscription in the sense of unsubscribe()-able objects returned by rxNostr.use(), we use the terms REQ subscription / Rx subscriptions in this document. In fact, the latter is strictly equivalent to Subscription in RxJS.

Forward Strategy

Forward Strategy is a strategy to listen to future events. The RxReq generated by createRxForwardReq() is based on this strategy. Under this strategy:

  • Each ReqPacket establishes REQ subscriptions that have the same subId. That is, old REQ subscriptions are overwritten, and always one or less REQ subscription is held.
  • REQ subscriptions will be CLOSE'd if any of the following occur:
    • When Rx subscription is explicitly unsubscribe()'d.
    • When CLOSE message is received for a reason other than an AUTH request.
    • When RxNostr is explicitly dispose()'d.

Note

To avoid duplicate retrieval of past events, it is recommended to adjust the since and limit of the ReqPacket to be sent out after the second time.

Backward Strategy

Backward Strategy is a strategy to listen to past events. The RxReq generated by createRxBackwardReq() is based on this strategy. Under this strategy:

  • Each ReqPacket establishes REQ subscriptions that have different subIds from each other. That is, multiple REQ subscriptions may run concurrently.
  • REQ subscriptions will be CLOSE'd if any of the following occur:
    • When an EOSE message is received.
    • When EVENT messages cannot be received for a certain period of time.
    • When Rx subscription is explicitly unsubscribe()'d.
    • When CLOSE message is received for a reason other than an AUTH request.
    • When RxNostr is explicitly dispose()'d.

WARNING

Since the Backward Strategy works assuming all REQs to return EOSE, you should adjust until etc. to avoid capturing future events.

Otherwise, REQ subscriptions may remain until the Rx subscriptions are explicitly unsubscribe().

Note

By default, it is CLOSE'd after 30 seconds of no EVENT messages being received. This time can be changed with the eoseTimeout option of createRxNostr().

over()

When issuing multiple REQs based on the Backward Strategy, it is sometimes useful to be able to wait for all of them to complete. The rxReq.over() function is only available with the Backward Strategy in such cases.

rxReq.over() tells rx-nostr that no more rxReq.emit() calls will be made on the same rxReq. After rxReq.over() is called, rxNostr.use() completes when the EOSE associated with all ReqPackets already sent out are confirmed (or immediately if all EOSE have already been confirmed). The completion process can be registered as follows:

ts
const rxReq = createRxBackwardReq();

rxNostr.use(rxReq).subscribe({
  next: (packet) => {
    console.log("Received:", packet);
  },
  complete: () => {
    console.log("Completed!");
  },
});

rxReq.emit({ ids: ["..."] });
rxReq.emit({ ids: ["..."] });

rxReq.over();

RxJS Tips

The concept of completion here is identical to the concept of Observable's completion in RxJS. Observable based on the Forward Strategy will never be completed (unless RxNostr is dispose()).

REQ Queue

Normally, relays are capped on the number of concurrent REQ subscriptions they can have, and these limits are exposed according to NIP-11. rx-nostr automatically reads this information and queues REQ requests so as not to violate the concurrency limit.

For more information, see NIP-11 Registry.