Search code examples
javascriptnode.jsasynchronousblockingpromise

Do object literals block in node.js


Do object literals block? I am trying to store the results of other functions in my pagination helper class and my Mocha tests fail due to timeout because the callback is not returned. If I remove local from all my variables (i.e. local.count to count) and I remove the .then holding the callback and place it in the first .then it suddenly works.

   render: (model, query, cb) =>
    self = @ 
    count = 0 
    local = {}

    count_promise = @query_count model, query

    count_promise.then (c) ->
      local.count = c 
      local.pages = self.pages(count)
      local.prev_class = self.prev_class(pages)
      local.next_class = self.next_class(pages)
      local.prev_page = self.prev_page(pages)
      local.next_page = self.next_page(pages)
    .then ->
      cb({num_pages: local.pages, current_page: self.page, prev_class: local.prev_class, next_class: local.next_class, prev_page: local.prev_page, next_page: local.next_page, results: {}})

    .fail (err) ->
      throw new Error(err)

    return

EDIT

I added console.log before the callback to see if anything showed up.

.then ->
      console.log local
      cb({num_pages: local.pages, current_page: self.page, prev_class: local.prev_class, next_class: local.next_class, prev_page: local.prev_page, next_page: local.next_page, results: {}})

Nothing came across.

The Mocha testing code for this particular method using Sinon and Chai Asserts:

describe 'PaginationHelper', ->

  describe 'Pagination Helper Initializes', ->
    it 'accepts page', ->
      assert.ok(new PaginationHelper(2))

  describe 'method testing', ->

    describe 'render method', ->
        ph = new PaginationHelper(2)
        result = {}

        before (done) ->
          ph.render BlogModel, {}, (res) ->
            result = res
            done()

        it 'returns object', ->
          assert.isObject(result)

        it 'returns object with num_pages', ->
          assert.property(result, "num_pages")

        it 'returns object with current_page', ->
          assert.property(result, 'current_page')

        it 'returns object with prev_class', ->
          assert.property(result, 'prev_class')

        it 'returns object with next_class', ->
          assert.property(result, 'next_class')

        describe 'render output testing', ->
          result = undefined

          before (done) ->
            ph = new PaginationHelper(1)
            ph.render BlogModel, {}, (res) ->
              result = res
              done()

          it 'returns a number for num_pages', ->
            assert.isNumber(result.num_pages)

          it 'returns a number for current_page', ->
            assert.isNumber(result.current_page)

          it 'returns string for prev_class', ->
            assert.isString(result.prev_class)

          it 'returns string for next_class', ->
            assert.isString(result.next_class)

The result output of this test:

Error: Command failed:   ✖ 1 of 35 tests failed:

  1) PaginationHelper method testing render method "before all" hook:
     Error: timeout of 2000ms exceeded

Solution

  • I figured out the issue. I didn't understand the chaining of thenables correctly until I delved into the Q promises API heavily. There were also stupid mistakes in variables I didn't correct. Coding while super tired is not cool. Here is how the code should look:

    render: (model, query, cb) =>
        self = @  
    
        count_promise = @query_count model, query
    
        count_promise.fail (err) ->
          throw new Error(err)
        .then (c) ->
          defer = Q.defer()
          local = {}
          local.count = c 
          local.pages = self.pages(local.count)
          local.prev_class = self.prev_class(local.pages)
          local.next_class = self.next_class(local.pages)
          local.prev_page = self.prev_page(local.pages)
          local.next_page = self.next_page(local.pages)
          defer.resolve(local)
          return defer.promise
        .then (local) ->
          cb({num_pages: local.pages, current_page: self.page, prev_class: local.prev_class, next_class: local.next_class, prev_page: local.prev_page, next_page: local.next_page, results: {}})
        return