Search code examples
promiseloopbackjs

autoupdate models with loopback lb3 - async trap


I'm just going crazy on this, can some help me please.

Perhaps someone has already solved this properly?

So I have an app with multiple datasources and I want them to autoupdate properly. Yet I can't believe that I have to do this... Shouldn't it be like a commun thing ?

I put this script in server/boot/20-autoUpdateDb.js


'use strict';

var cluster = require('cluster');

module.exports = function(app, cb) {
  if (cluster.isWorker) {
    process.nextTick(cb);
  } else {

    const updateDS = async dataSources => {
      await dataSources.forEach(async (ds, key, arr) => {
        if (ds.autoupdate) {
          console.log('Proceeding with dataSource:', ds.name);

          const x = await new Promise(r => {
            ds.autoupdate(err => {
              if (err) throw err;

              console.log(
                // 'Auto Updated Models [' + Object.keys(app.models) + ']:',
                'Auto Updated Models in',
                ds.name,
                '(',
                ds.adapter.name,
                ')',
              );

              r();
            });
          });
        }
      });
    };

    // I just couldn't find a better way as all datasources
    // exist in double ex: db,Db 

    var appDataSources = [
      app.dataSources.db,
      app.dataSources.dbData,
      app.dataSources.dbPool,
    ];

    updateDS(appDataSources).then(() => {
      console.log('Autoupdate of all models done.');
      process.nextTick(cb);
    });
  }
};

as output I get

Proceeding with dataSource: db
Proceeding with dataSource: dbData
Proceeding with dataSource: dbPool
Auto Updated Models in dbPool ( sqlite3 )
Autoupdate of all models done.
Web server listening at: http://localhost:3000
Browse your REST API at http://localhost:3000/explorer
Auto Updated Models in dbData ( sqlite3 )
Auto Updated Models in db ( sqlite3 )

Solution

  • Array.prototype.forEach doesn't wait for promises. Try this:

    const appDataSources = [
      app.dataSources.db,
      app.dataSources.dbData,
      app.dataSources.dbPool,
    ]
    
    (async () => {
      for (let i = 0; i < appDataSources.length; i++) {
        const ds = appDataSources[ i ]
    
        if (ds.autoupdate) {
          await new Promise((resolve, reject) => {
            ds.autoupdate(err => {
              if (err) return reject(err)
              resolve()
            })
          })
        }
      }
    })()