0

Using MySQL, Node.js, Knex, Promise.

First time work with Promise, Knex and Node. I am not able to achive given task because of Promise and async calls I am not used to them.

The idea is the following - having two tables (products and parts). Data were migrated there using some bulk inserts. There is in-between table "products_parts", it is not filled and I need to create node js code to fill in this table. When data would be filled in, then in the futre we would still need sometimes to call this function for some seperate products.

Here is algorithm:

  1. Query products
  2. For each product that is queried - take product.description and divide it into parts (split by commas). For instance, if description = "A1, B1, C1" then we would have three parts - A1, B1 and C1 and need process each of them.
  3. Do next step with with products part (call it PART) - this is written in FOR loop now, but probably should be somehow replaced by Promise something.

  4. Try to find PART in database "parts" table.

    • If found then do insert into db "product_parts".
    • If not found then first populate "PARTS" table with newly found PART. And then also populate "product_parts" table.

I started like this:

knex("products")
    .select("id", "description")
    .map(function (row) {
        // do staff with products.descriptin, simplified version:
        var descriptionSplitByCommas = desc.split(",");  

        // do staff with each description PART here
        // This for is not async and I believe is a bad idea, but how?!
        for (var k = 0; k < descriptionSplitByCommas.length; k++) {
          // STEP 3-4 should be here

          // normalisation includes some string functions to be called
         d = get_normalised_description(descriptionSplitByCommas[k]);
         knex("PARTS")
            .where("name", "=", d)
            .first()
            .then(function (row) {
                if (row != undefined) { //not found
                    // do knex insert into "product_parts" table
                } else {
                   // do knex insert into "PARTS" table
                   // do knex insert into "PRODUCT_PARTS" table 
                }
          })
        }
    })
renathy
  • 5,125
  • 20
  • 85
  • 149
  • So what is the problem? Other than the code not provided and replaced with comments I see no problem. If the function in `.then` uses the variable k then you're in trouble because you probably need to return `knex("PARTS")` in an IIFE so to trap the value of k in a [closure](https://stackoverflow.com/q/750486/1641941). – HMR Jan 09 '18 at 12:12
  • 1
    Instead of `for (var k = 0; k < descriptionSplitByCommas.length; k++) {` you'd better return `return Promise.all(descriptionSplitByCommas.map(description=>...` far simpler and no closure or IIFE needed like my first comment. – HMR Jan 09 '18 at 12:15
  • @Hmr I believe tghat for loop would be incorrect as it is not Promise like. Inside for loop there would be multiple thens. And I am trying know with Promise.all. – renathy Jan 09 '18 at 12:44

1 Answers1

0

Maybe the following will work but since the code that doesn't work is in your comments I can't be sure:

knex("products")
    .select("id", "description")
    .map(function (row) {
      return Promise.all(
        desc.split(",")
        .map(get_normalised_description)
        .map(
          descripion=>
            knex("PARTS")
            .where("name", "=", descripion)
            .first()
            .then(function (row) {
              return Promise.all([
                //insert into product_parts table,
                //(row!==undefined)
                //  ? undefined
                //  : insert into parts table
              ])
            })
        )
      )
    })
HMR
  • 37,593
  • 24
  • 91
  • 160