-1

Basically I need to wait the result of the insert query made with Bookshelf.js, because I need the id provided by the query to insert a row in my DB

I don't understand some aspects of the asynchronous behavior of Node and its components

So the problem is in this part of the code:

Insert Method Bookshelf

var new_timer = new Timer({
                titolo: title,
                time: timerVal,
                created: creation,
                ended: ended,
                id_owner: owner
            });
new_timer.save(null, {method: "insert"}).then(function(model){
    if(!model)
        return res.send({status: 400, url: "/add"});
    associateTag(model.id_timer, tags);
    return res.send({status: 200, url: "/"});
});

functions used

var insertAssociation = function(timerID, tags) {
     return knex.table('timer_tag').insert({id_tmr: timerID, id_tg: tags.id_tag});
}

var associateTag = function(timerID, tags) {
    var id_tag;
    for(var i = 0; i < tags.length; i++){
        getTagByName(tags[i]).then(function(result) {
            console.log(result);
            insertAssociation(timerID, result[0]).then(function(k) {
                console.log(k);
            });
        });
    }
}

var getTagByName = function(name) {
    return knex.table('tags').select('id_tag').where('nome_tag', name);
}
Ivan Bertola
  • 301
  • 1
  • 3
  • 12
  • Possible duplicate of [How to return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Veve Nov 14 '17 at 13:02

1 Answers1

2

Replace

for(var i = 0; i < tags.length; i++){
        getTagByName(tags[i]).then(function(result) {
            console.log(result);
            insertAssociation(timerID, result[0]).then(function(k) {
                console.log(k);
            });
        });
    }

By

Promise.all(tags.map(x => getTagByName(x)
   .then((result) => insertAssociation(timerID, result[0]))))

You were launching asynchronously several requests. What I do is using Promise.all in order to wait all of theses requests to finish.


EDIT: Full example

  new_timer.save(null, {
    method: 'insert',
  }).then((model) => {
    if (!model) {
      res.send({
         status: 400,
         url: '/add',
      });

      return;
    }

    associateTag(model.id_timer, tags)
      .then((allRets) => {
          console.log(allRets);

          res.send({
            status: 200,
            url: "/"
          });
      })
      .catch(e => {
        // error handling
      });
  })
  .catch(e => {
    // error handling
  });

  var associateTag = function (timerID, tags) {
    return Promise.all(tags.map(x => getTagByName(x)
      .then((result) => insertAssociation(timerID, result[0]))));
  }
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
  • I tried to replace the code you provided but it doesn't work... I tried to log the `timerID` but it returns `undefined` – Ivan Bertola Nov 14 '17 at 15:27
  • 1
    So I managed to resolve the issue... I was using the `model` element wrong, I replaced `model.id_timer` with `model.attributes.id_timer`, also now I understand better the async behavior thanks to your answer – Ivan Bertola Nov 14 '17 at 16:29