0

I'll try to make this short.

The code in Example 1 works fine, like it should, but the code in Example 2 does not, and the only difference is that it's started with an ajax call(in this case a dummy one). The call get's the array that will be parsed. But in 'then' function it just goes to the first furthest 'tree' branch and stops. How does 'then' cause this?

It's supposed to be a 'tree like' walk through.

Codepen Example 1

$(function() {
  $('button').on('click', function() {
    runSequence('list_one').then(function() {
      document.getElementById('output').innerHTML += 'Done<br>';
    });
  });
});

let lists = {
  list_one: [{Action: '@ActionOne: argument', ListNo: '1'}, {Action: '@ActionList: list_two', ListNo: '1'}, {Action: '@ActionThree: argument', ListNo: '1'}],
  list_two: [{Action: '@ActionOne: argument', ListNo: '2'}, {Action: '@ActionList: list_three', ListNo: '2'}, {Action: '@ActionThree: argument', ListNo: '2'}],
  list_three: [{Action: '@ActionOne: argument', ListNo: '3'}, {Action: '@ActionTwo: argument', ListNo: '3'}, {Action: '@ActionThree: argument', ListNo: '3'}],
};

var runSequence = (function(name) {
  return initSequence(lists[name]);
});

var initSequence = (function(sequence) {
  return sequence.reduce(function(sequence, action) {
    let act = action['Action'];
    let actName = act.substr(0, act.indexOf(':')).trim();
    let actArg = act.substr(act.indexOf(':')+1).trim();
    document.getElementById('output').innerHTML += action['ListNo'] + ' - ' + actName + ': ' + actArg + '<br>';
    return executeAction(actName, actArg);
  }, Promise.resolve());
});

var executeAction = (function(actionName, actionArgument) {
  if(actionName == '@ActionList') {
    return runSequence(actionArgument);
  }
  return Promise.resolve();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>start</button>
<div id="output"></div>

Codepen Example 2

$(function() {
  $('button').on('click', function() {
    runSequence('list_one').then(function() {
      document.getElementById('output').innerHTML += 'Done<br>';
    });
  });
});

let lists = {
  list_one: [{Action: '@ActionOne: argument', ListNo: '1'}, {Action: '@ActionList: list_two', ListNo: '1'}, {Action: '@ActionThree: argument', ListNo: '1'}],
  list_two: [{Action: '@ActionOne: argument', ListNo: '2'}, {Action: '@ActionList: list_three', ListNo: '2'}, {Action: '@ActionThree: argument', ListNo: '2'}],
  list_three: [{Action: '@ActionOne: argument', ListNo: '3'}, {Action: '@ActionTwo: argument', ListNo: '3'}, {Action: '@ActionThree: argument', ListNo: '3'}],
};

var runSequence = (function(name) {
  return sendRequest('sequence', 'test').then(function(res) {
    return initSequence(lists[name]);
  });
});

var initSequence = (function(sequence) {
  return sequence.reduce(function(sequence, action) {
    let act = action['Action'];
    let actName = act.substr(0, act.indexOf(':')).trim();
    let actArg = act.substr(act.indexOf(':')+1).trim();
    document.getElementById('output').innerHTML += action['ListNo'] + ' - ' + actName + ': ' + actArg + '<br>';
    return executeAction(actName, actArg);
  }, Promise.resolve());
});

var executeAction = (function(actionName, actionArgument) {
  if(actionName == '@ActionList') {
    return runSequence(actionArgument);
  }
  return Promise.resolve();
});

var sendRequest = (function(type, param) {
  return $.ajax({
    url: '//posttestserver.com/post.php',
    method: 'post',
    data: JSON.stringify({
      type: type,
      param: param
    })
  }).then(function(response, status, xhr) {
    return response;
  }, function(xhr, status, error) {
    return error;
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>start</button>
<div id="output"></div>

EDIT (FIX) : The problem was jQuery 2.x as it was messing up with promises, using jQuery 3.x solved the problem. Also reduce was not a good idea to use here. Replaced it with each from Bluebird to make it work like it should.

IntoDEV
  • 31
  • 8
  • 1
    Because jQuery. What version are you using? Try wrapping the `$.ajax()` in a `Promise.resolve(…)` – Bergi Apr 05 '16 at 13:37
  • Your `initSequence` function doesn't make much sense. What is it supposed to do? Why does the reducer ignore the `sequence`? – Bergi Apr 05 '16 at 13:39
  • @Bergi the initSequence function is a 'foreach' function – IntoDEV Apr 05 '16 at 13:40
  • Not really. It just returns `executeAction(…)` for the last action in the `sequence`, and fires off a bunch of other promises that are subsequently ignored. – Bergi Apr 05 '16 at 13:43
  • @Bergi Have you even looked at the snippet 'Example 1'? It is clearly visible that everything is working fine, the initial ajax request before firing 'runSequence' is what seems to be not working correctly here and I don't know why. – IntoDEV Apr 05 '16 at 13:46
  • @Bergi `The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.`. Straight from MDN [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) – IntoDEV Apr 05 '16 at 13:47
  • I know that it's acting differently (see the duplicate why), and this has nothing to do with the `reduce`. I'm just suggesting that `reduce` does not do what you expect it to do - it does not wait for promises. – Bergi Apr 05 '16 at 13:51
  • 1
    @Bergi Thank you. I've replaced `reduce` back to bluebird `each` and replaced jQuery 2.x with jQuery 3.x and it actually works now. Took me almost a week with side jobs in between to finally continue my work on this project :) – IntoDEV Apr 07 '16 at 13:18

0 Answers0