Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

195
Vistas
Can I add side-effects to scan

I have a problem: "When a mouse down, create a rectangle, resize it when move and complete when a mouse up". I tried to use rxjs, but it is not really good solution:

import { scan, mergeMap, takeUntil, fromEvent } from 'rxjs';

const mouseDown$ = fromEvent(document, 'mousedown');
const mouseUp$ = fromEvent(document, 'mouseup');
const mouseMove$ = fromEvent(document, 'mousemove');

function createNode() {
  const node = document.createElement('DIV');
  node.setAttribute('style', 'position: absolute; border: 1px solid red;');
  document.body.appendChild(node);
  return node;
}

mouseDown$
  .pipe(
    mergeMap(() => {
      return mouseMove$.pipe(
        takeUntil(mouseUp$),
        scan((node, e: MouseEvent) => {
          if (!node) {
            let x = null;
            x = createNode();
            x.style.top = `${e.clientY}px`;
            x.style.left = `${e.clientX}px`;
            return x;
          } else {
            node.style.bottom = `${e.clientY}px`;
            node.style.right = `${e.clientX}px`;
          }
          return node;
        }, null)
      );
    })
  )
  .subscribe(() => {});

The problem is the side-effects is added to the method "scan" Do you have much better solution for this problem?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

If you want to avoid a inner pipe side-effect (what is in general a good thing) you can split your logic into two different Observables/Subscriptions:

Create Node Observable

let node = null

const createNode$ = mouseDown$.pipe(
  switchMapTo(mouseMove$.pipe(
    takeUntil(mouseUp$),
    take(1)
  ))
)

createNode$.subscribe(createNode)

function createNode(e: MouseEvent) {
  const node = document.createElement('DIV');
  node.setAttribute('style', 'position: absolute; border: 1px solid red;');
  document.body.appendChild(node);
  x.style.top = `${e.clientY}px`;
  x.style.left = `${e.clientX}px`;
  return node;
}

Update Node Obsservable

const updateNode$ = mouseDown$.pipe(
  switchMapTo(mouseMove$.pipe(
    takeUntil(mouseUp$),
    skip(1)
  ))
)

updateNode$.subscribe(updateNode(node))

function updateNode(node: Node) {
  return function(e: MouseEvent) {
    node.style.bottom = `${e.clientY}px`;
    node.style.right = `${e.clientX}px`;
  }
}

I do not prefer the above one to your solution - they are both equal imo. It's just a way to possibly avoid side-effects. There are several opinions onto when and why to avoid side-effects. I personally try to reduce them as much as I can but there are some scenarios where it's just not worth going for it (or I might just have not seen a good solution).

I once asked a question about when-should-i-create-a-new-subscription-for-a-specific-side-effect. The answer can give you some details about when and why it can be useful to avoid side-effects.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda