2

I have a block of jquery that builds a form with more than 40 element using a loop to .append() div elements that load .ajax() json.

9 out of 10 times the form renders as expected. However randomly some of the elements will suffer from two types of errors

  1. the dom element will be created but not displayed (does not show in source)(on deeper investigation, it seems the elements are always generated, just wrong parent (2))
  2. the dom element is placed as a child to the wrong parent.

for example below, id3 should be attached to delta[14] but is instead generated at beta[3] OR id3 should be at gamma[6] but does not display at all

the format of build is

hard code

<div id="alpha">
   <div id="beta"></div>
   <div id="gamma"></div>
   <div id="delta"></div>
</div>

doAppendStuff(beta, ajaxUrletc1);
doAppendStuff(beta, ajaxUrletc2);
...
doAppendStuff(gamma, ajaxUrletc10);
doAppendStuff(gamma, ajaxUrletc11);
...
doAppendStuff(delta, ajaxUrletc20);
doAppendStuff(delta, ajaxUrletc21);

dynamic

    function randId(baseID) {
        return baseID+"_"+Math.round(new Date().getTime() + (Math.random() * 555));
    }

    var id1= randId("myIdOne");
    var id2= randId("myIdTwo");
    var id3= randId("myIdThree");

    function doAppendStuff(elemId, ajaxUrletc){
    $('#' + elemId).append(
        '<div id="' + id1 + '" >' +
           '<div id="' + id2 + '">' +
              '<select id="' + id3 + '"></select>' +
            '</div>' +
        '</div>'
     );
    ... // log id1, id2,id3
    ... //do .ajax stuff + callback on id3

I have added callbacks to each loop to ensure that the .append is fired and no errors are generated complaining that the element does not exist.

Running a trace I can see the dynamic id for each element is being generated.

The code itself works as expected as the other 9/10 times it renders as expected.

notes

  1. The random errors apply to different elements each time. no particular logic on what element fails.
  2. I have separated the ajax calls from the dom element creation so there should be no bottleneck on the element creation
  3. All ajax calls are initiated as expected in the correct order. Some take longer but the other elements generate as expected without waiting. All data is successfully returned.

Is there any know issues with generating multiple dom elements by calling the same function repeatedly OR is there a listener I could add to ensure the element is correctly generated in the desired position before proceeding to the next call via a callback.

UPDATE

After adding logging of the id1,id2,id3, the logs confirm that the correct dynamic ids are being assigned. It seems however that either the var in memory is being replaced with a previous value or the js engine is placing in the wrong generated position due to timing.

UPDATE 2

After some more debugging, we changed the random string and upped the number from

return baseID+"_"+Math.round(new Date().getTime() + (Math.random() * 555));

to

return baseID+"_"+Math.round(new Date().getTime() + (Math.random() * 99999));

and the problem has not reoccurred. So it looks like it could be either a random ID collision with the same string being generated twice or somehow reused when the function is reinitialised. The interesting thing is the ID's are not sequential, it will often skip several rows before reusing the same ID.

So we have cured the problem, but still do not understand what caused the issue, any thoughts are welcome.

art vanderlay
  • 2,341
  • 4
  • 35
  • 64
  • 2
    There's no issues with dynamically created elements, but the ajax calls are not guranteed to respond in the same order they've been send. – Teemu Sep 22 '17 at 17:45
  • Try using Try-catch block so that at least you get to know the error if exists. – Rex Sep 22 '17 at 17:47
  • Can you show us some code inside the ajax succes/failure callback? I think your problem has to do with .ajax() being async. – Thibault Fouquaert Sep 22 '17 at 17:50
  • why are you assigning the same ID to multiple elements? It looks like `doStuffAppend` is built to call multiple times.... A ID is suppose to be unique to the document. – Fallenreaper Sep 22 '17 at 18:28
  • @Fallenreaper, it is not assigning same id. it is assigning a prefix+rand string. – art vanderlay Sep 22 '17 at 18:31
  • @artvanderlay you arent calling `ranId()` multiple times as far as i see, so it all ids assigned by id1 would be the same. – Fallenreaper Sep 22 '17 at 19:49
  • Date().getTime() returns the number of milliseocnds since January 1st 1970. So "abc" + new Date().getTime() could return "abc1506110581013". After rounding, Math.random() * 555 will return between 0 and 554. So there is a chance it would pick a number that will match a future call of the same thing run some ms later. This is assuming you are making multiple calls over time. Ignoring the prefix, What you're doing in Edit 2 is closer to just using a random id, to be honest, while before what you were doing was closer to just using the regular time. – Greg Sep 22 '17 at 20:09

1 Answers1

2

If you want a unique value, then we're talking about GUID's.

Create GUID / UUID in JavaScript?

However, if you would have placed an underscore or other value between the time and random number, I'd suspect you'd have seen fewer collisions.

time + random = some future period in time.

Imagine getting a random 100 and then 100 ms later getting a random 0.

"abc1506110581013_100" != "abc1506110581113_0"

while

"abc1506110581113" == "abc1506110581113"

Greg
  • 2,410
  • 21
  • 26
  • Or, if you only need unique id's for your session, use `function randID(baseID) { return _.uniqueId(baseID); }` using underscorejs or lodash library. Guaranteed unique ids for your session. – Brandon Sep 22 '17 at 20:17
  • Also of question is why do you need an id? You can do a lot with just classes, and finding elements that are children or closest parent of another element. It also doesn't take an id to find the nth element, even elements, odd elements, or many other css selectors that jquery uses. – Greg Sep 22 '17 at 20:23
  • @Greg, I had not thought of the time issue like that. Thanks for the pointer of separating the time_random. Makes a lot of sense given the non sequential order when the problem generates. Art – art vanderlay Sep 23 '17 at 08:47