Wait, did I do this right?
Tags: javascript, node, meteor, showdev
Published: 2017-09-23 17:05:48

---
title: Wait, did I do this right?
published: true
description: Trying to code a synchronous queue in Javascript
tags: javascript, node, meteor, showdev
---

## Introduction

I had to solve an issue at work this week. In our meteor application, the goal was to make sure that certains actions were synchronous. If we had two tabs open, one would deposit money, then the other tab could be used to buy something. We needed to make sure that the second action could not happen before the first. 

So, the goal was to build a synchronous queue in meteor. The queue had to be inside its own module and couldn't be called directly from the front-end ( so it had to be outside the method ). I REALLY struggled. It took me more than a day, but I learned a lot. I used promises to solve my problem. I am curious if another ( better? ) solution could have been used. There are most likely better ways to do this, so I would like your opinions.

## The code

*Sets the background*

*Cue epic music*

*Show a character's face, with a tear rolling down her cheek*

*Slowly turn the camera towards the code*

*Build up the music...*

<img src='http://www.alicia-logic.com/capsimages/LOTR_Fell086_ElijahWood.jpg' />


#### *Front-end*

```javascript
//The method called by the front-end, the same one for all activities

Meteor.callPromise( 'handleActivity', data)
    .then( () => {
        // Do something on the front when action is handled on the back
    }
    .catch( err => {
        // Do something on the front when an error occurs
    })
```

#### *Back-end*

##### *The meteor method handleActivity*

```javascript
Meteor.methods({
    handleActivity( data ){
        return new Promise( ( resolve, reject ) => {
            SyncQueue.add( data )
                .then( () => {
                    // back to front. Everything OK
                    resolve()
                    }
                })
                .catch( err => reject( err )) // Error, back to front
    }
})
```

*SyncQueue* is the name of the module that holds the synchronous queue implementation.

##### *SyncQueue*

```javascript
const SyncQueue = ( function(){
    let isProcessing = false
    let _actions = [] // stores actions's data
    
    const add = data => {
        return new Promise( ( resolve, reject ) => {
            _actions.push([data, resolve, reject])
            
            if( !isProcessing ){
                isProcessing = true
                return next()
            }
        })
    }

    const next = () => {
        if( _actions.length > 0 ){
            return processAction( _actions.shift() ) //Take the first action 
        } else {
            isProcessing = false
            return false // I don't know... just returning something I guess
        }
    }

    const processAction = action =>Â {
        const [ data, resolve, reject ] = action
        const func = // a function ref I retrieve thanks to the activity type
        
        func()  //These functions also return promises
            .then( () => {
                resolve() 
                // this is the resolve from the add method 
            })
            .catch(err => {
                reject( err )
                // this is the reject from the add method
            })
            .then( () => {
                // Always runs yes ?
                // Any more data to process ?
                return next()
            }
    }
    return {
        // Only needs to show the add method
        add
    }
})()
```

Well, there you have it. I'm glad I solved it. I have no idea if this is elegant, or even following proper best practices. I also like that I didn't use callbacks... I wonder how I could have done it with async/await. I'm also aware that my lack of knowledge about Meteor was certainly a problem. I guess I could have used built-in functionalities to solve this?

Anyway, what do you think? Did I overcomplicate things? How would you have solved it? Would love to hear ideas :)