vue-rx: how to watch value of object from an array is not change anymore?

606 views Asked by At
"vue-rx": "^6.1.0",
"rxjs": "^6.4.0",
"vue": "^2.5.17",

I'm new in vue-rx and rxjs,But when I see several demo of rx, I'm quite interested in this.So I want to use it in my project which posts a request when attribute num will not change anymore

[
  {
    id: 0,
    name: 'giftA',
    num: 0 // will turn to 1,2,3,4,5,...after running `send({id: 0})` function 1,2,3,4,5,...times
  },
  {
    id: 1,
    name: 'giftB',
    num: 0
  },
  ...
]

And Here is my solution:

using $watchAsObservable to watch the change of sendCalledTimes, and then using mergeMap to post the request.

the variable sendCalledTimes is a number which will sendCalledTimes++ when called send function, And after posting the request, reset this to sendCalledTimes = 0.

So that $watchAsObservable('sendCalledTimes')(vue-rx) will execute every three seconds, and will reduce request times in my project. But i think it's still not good because it just like a timer and can't watch weather num of each object in the Array changes. The good example should be like this search example.

data() {
  return {
    sendCalledTimes: 0,
    giftArr: []
  }
},
created() {
  this.$watchAsObservable('sendCalledTimes').pipe(
      pluck('newValue'),
      filter(val => val > 0),
      debounceTime(3000),
      // if `sendCalledTimes` is the same number as previous
      // will not execute follows
      // distinctUntilChanged(), 
      mergeMap(
        (val) => this.requestSendGift()
      ),
    ).subscribe(
      (val) => {  }
  )
},
methods: {
  send (obj) {
    let pushFlag = true
    for (const gift in this.giftArr) {
      if (gift.id === obj.id) {
        gift.num++
        pushFlag = false
        break
      }
    }

    if (pushFlag) {
      this.giftArr.push(obj)
    }
    // observable
    this.sendCalledTimes++
  },
  async requestSendGift () {
    for (const gift in this.giftArr) {
      // example for post a request to store each gift
      await axios({
        data: gift,
        type: 'post',
        url: '...'
      }).then(res => { ... })
    }
    // reset `this.sendCalledTimes`
    this.sendCalledTimes = 0
  }
}

Also since vue-rx doesn't have many examples on github, so i need help to solve creating good subscription for this situation.

I have tried this, but failed:

data () {
    return {
        giftArr: []
    }
},
subscriptions: {
    test: from(this.giftArr) // console.log(this.$observables.test) throw an error: typeError: Cannot read property 'giftArr' of undefined
},

It would be greatly appreciated if anyone can help me to solve this question.

1

There are 1 answers

2
Corey On

It's a little unclear from your question exactly what you're trying to do, but I've created an example based on what I believe to be your intent.

I made some assumptions:

  • You have a 'gifts' array that represents all of the gifts that will ever exist.
  • You want to make updates to that array.
  • Every time you make an update to the array, you want to see the update in the form of an Observable emitting an event.

Use a Subject

I think what you want is a Subject.

const gift$ = new Subject();

Make it Emit on Updates

And you would set it up to emit every time you increment num or add a new gift.

function addGift(gift) {
  gifts.push(gift);
  gift$.next(gift);
}

function incrementGift(gift) {
  gift.num++;
  gift$.next(gift);
}

All together it could look something like this:

import { Subject } from 'rxjs';

const gift$ = new Subject();
const gifts = [{ id: 0, name: 'giftA', num: 0 }, { id: 1, name: 'giftB', num: 0 }];

function addGift(gift) {
  gifts.push(gift);
  gift$.next(gift);
}

function incrementGift(gift) {
  gift.num++;
  gift$.next(gift);
}

function sendGift(newGift) {
  const currentGift = gifts.find(g => g.id === newGift.id);
  currentGift ? incrementGift(currentGift) : addGift(newGift);
}

gift$.subscribe(update => {
  console.log(gifts);
  console.log(update);
});

// You should see an initial logging of 'gifts' and update will be 'undefined' at first. Then you'll see a log for every 'sendGift'.

sendGift({ id: 0 });
sendGift({ id: 3, name: 'giftC', num: 0 });

StackBlitz