Verify AngularJS select data before inserting

As a newcomer to angularjs, I decided to practice using the ionic framework which involves angularjs. However, I encountered a slight issue. I want to check if data already exists before inserting new data.

In the method getContent.then(function(res){}), I am checking the return value of res.length. If it is equal to 0, then I proceed with inserting the data. When I run the code, the console displays the data stored in the variable obj. But in the end, when I try to retrieve all the data, it appears empty.

I noticed that if I move the insert method outside the getContent.then(function(res){}) function, it works fine. I'm unsure about how to resolve this issue or what might be causing it.

Thank you for your assistance.

This is my Controller code:

angular.module('starter.controllers', ['sqlite.services'])
.controller('TestCtrl', function($scope, $http, Tests, SQLService) {
  SQLService.setup();
  var new_tests = new Array();

  $http.get('https://XXXXX').then(function(response){
    var datas = response.data;
    for (data_ in datas) {
      var obj = {
        id: datas[data_].content_id,
        title: datas[data_].title,
        url: datas[data_].url,
        content: datas[data_].content
      };

      var getContent = SQLService.get_one(obj.id);
      getContent.then(function(res) {
        console.log('res ' , res);
        console.log('res ' , res.length); // length get 0

        if(res.length == 0) {
          console.log('insert obj ' , obj);
          console.log('SQLService ' , SQLService);
          SQLService.insert(obj);
        }
        else if (res.length == 1) {
          console.log('edit obj ' , obj);
        }
      });

      // SQLService.insert(obj); // If I write insert code here is work for me

      new_tests.push(obj);
    }
  })
  .finally(function() {
    SQLService.all().then(function (results) {
      $scope.tests = results;
      console.log('results ' , results);
    });
  });

This is my sql_service.js

angular.module('sqlite.services', [])
.factory('SQLService', function($q) {
  var db;

  function createDB() {
    try {
      if (window.cordova) {
        $cordovaSQLite.deleteDB("my.db");
        db = $cordovaSQLite.openDB({name: 'my.db'}); // device
      }
      else{
        db = window.openDatabase("my.db", '1', 'my', 1024 * 1024 * 100); // browser
      }

      db.transaction(function(tx) {
        tx.executeSql("CREATE TABLE IF NOT EXISTS pixnet (id integer not null primary key autoincrement, content_id text, title text, url, text, content text)", []);
      });
    }
    catch(err) {
      console.log('Error processing SQL: ' + err);
    }

    console.log('database created');
  }

  function insertNewContent(newContent) {
    console.log('--insert--');
    return promisedQuery("INSERT INTO pixnet (content_id, title, url, content) VALUES ('" + newContent.id + "', '" + newContent.title + "', '" + newContent.url + "', '" + newContent.content + "')", defaultResultHandler, defaultErrorHandler);
  }

  function getContents() {
    return promisedQuery("SELECT * FROM pixnet", defaultResultHandler, defaultErrorHandler);
  }

  function updateContent(content){
    console.log('update content ' , content);
    return promisedQuery("UPDATE pixnet SET title='" + content.title + "', content='" + content.content + "' WHERE content_id = '" + content.id + "'", defaultResultHandler, defaultErrorHandler);
  }

  function getContent(content_id) {
    return promisedQuery("SELECT * FROM pixnet WHERE content_id = '" + content_id + "'", defaultResultHandler, defaultErrorHandler);
  }

  function defaultResultHandler(deferred) {
    return function(tx, results) {
    console.log('defaultResultHandler results ' , results);
    var len = results.rows.length;
    var output_results = [];

    for (var i=0; i<len; i++){
      var t = {
        'id': results.rows.item(i).id,
        'content_id': results.rows.item(i).content_id,
        'title': results.rows.item(i).title,
        'url': results.rows.item(i).url,
        'content': results.rows.item(i).content
      };
      output_results.push(t);
    }

    deferred.resolve(output_results);
    }
  }

  function defaultErrorHandler(deferred) {
    return function(tx, results) {
    var len = 0;
    var output_results = '';
    deferred.resolve(output_results);
    }
  }

  function promisedQuery(query, successCB, errorCB) {
    var deferred = $q.defer();
    db.transaction(function(tx){
      tx.executeSql(query, [], successCB(deferred), errorCB(deferred));
    }, errorCB);
    return deferred.promise;
  }

  return {
    setup: function() {
      return createDB();
    },
    insert: function(content) {
      return insertNewContent(content);
    },
    edit: function(content) {
      return updateContent(content);
    },
    get_one: function(content_id) {
      return getContent(content_id);
    },
    all: function() {
      return getContents();
    }
  }
});

Answer №1

The issue at hand seems to be that the 'deferred' variable created in the promiseQuery function is not being resolved:

 function promisedQuery(query, successCB, errorCB) {
     var deferred = $q.defer();
     db.transaction(function(tx){
        tx.executeSql(query, [], successCB(deferred), errorCB(deferred));
     }, errorCB);
     return deferred.promise;
  }

With the Cordova sqlite plugin you are using, it appears that the third argument of the 'transaction' function should be the success callback.

https://github.com/brodysoft/Cordova-SQLitePlugin/blob/master/www/SQLitePlugin.js#L74

Therefore, you need to resolve your promise within one of those callbacks. You can try the following modification:

 function promisedQuery(query, successCB, errorCB) {
     var deferred = $q.defer();
     db.transaction(function(tx){
        tx.executeSql(query, [], successCB(deferred), errorCB(deferred));
     }, errorCB, deferred.resolve);
     return deferred.promise;
  }

By passing the deferred.resolve function into the success callback (as the last argument of transaction), it will be triggered upon completion of the transaction.

Answer №2

    angular.module('starter.controllers', ['sqlite.services'])
      .controller('TestCtrl', function($scope, $http, Tests, SQLService) {
          SQLService.setup();
          var new_tests = new Array();

          var call_async_in_loop = function(obj) {
            var getContent = SQLService.get_one(obj.id);
            getContent.then(function(res) {
              console.log('res ', res);
              console.log('res ', res.length); // length get 0

              if (res.length == 0) {
                console.log('insert obj ', obj);
                console.log('SQLService ', SQLService);
                SQLService.insert(obj);
              } else if (res.length == 1) {
                console.log('edit obj ', obj);
              }
            });

          }

          $http.get('https://XXXXX').then(function(response) {
              var datas = response.data;
              for (data_ in datas) {
                var newObj = {
                  id: datas[data_].content_id,
                  title: datas[data_].title,
                  url: datas[data_].url,
                  content: datas[data_].content
                };

                call_async_in_loop(newObj)
                new_tests.push(newObj);
              }
            })
            .finally(function() {
              SQLService.all().then(function(results) {
                $scope.tests = results;
                console.log('results ', results);
              });
            });

The reference to obj is lost due to the asynchronous call SQLService.get_one(obj.id). By the time the promise is resolved, the for loop has already finished executing. To maintain a reference to obj, you need to create a closure.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Failure when running npm start command in Nest js

After setting up a fresh Nest js on a new EC2 machine, I encountered an error when trying to run it for the first time. The error message indicated that the npm install process failed abruptly without any visible error: ubuntu@ip-172-31-15-190:~/projects/m ...

Comprehending the Syntax of the ExtJS Framework

I have recently inherited a project utilizing Sencha's ExtJS framework without any handover or documentation. As I navigate through the code, I find myself trying to decipher certain syntax and exploring resources tailored for newcomers to this specif ...

Unable to access the uploaded file on the server

Scenario : When a user uploads an image and clicks on the "save" button, I successfully save the image on the server with 777 permission granted to the folder... https://i.sstatic.net/gcIYk.png Problem : However, when I try to open the image, it does n ...

Exploring the benefits of integrating JQuery AJAX with non-unicode websites

Using JQuery's '.serialize' and '.post', I am sending form data via ajax to a non-unicode ASP-based website. The resulting data is URL-encoded in unicode, with characters encoded in double values. Is it possible to encode the form ...

Display data as a JSON object using Highcharts

Looking to populate a highchart in Jade using JSON data sent from Node.js. Currently, I have successfully added static data as shown in the code snippet below: var series = [ { name: 'Tokyo', data: [7.0] } ]; Now, I am attempti ...

Arrange moving shapes in the same spot

Every time I press the button, a unique shape is generated. These shapes are dynamic and can range from polygons to circles (there are hundreds of shapes). Each shape is composed of a series of lines. The problem arises when each shape is positioned diff ...

I seem to be having an issue with the decimal point on my calculator - I only want to see one dot

Only need one dot for the calculator to function properly. The current situation with multiple dots is causing confusion. I intend to address other aspects of the code later, but I'm currently struggling with this issue. function dec(d) { let ...

What is the best way to implement an automatic logout feature in asp.net that will log out my site after 10 minutes of inactivity?

Looking for a solution to automatically log out a site in asp.net when it is idle? Here's what you can do: Set the session timeout to 10 minutes in the web.config file under authentication. For instance, if the site has been idle for 9 minutes, you ca ...

Issues loading resource: bundle.js generates successfully in NodeJS and React app, however, error 404 occurs

I am currently working on a simple practice project where I have some initial content (a '...' string) in the JS environment. My goal is to load React after the JS environment loads and replace the content with a 'hello react' string wi ...

A method for retrieving the variables from the initial API function for use in a subsequent API function

$.getJSON(url, function (data) { $.getJSON(url_wind, function (data2) { //perform actions with 'data' and 'data2' }); }); While attempting to use the data from the initial getJSON() call in the second getJSON() call ...

The JavaScript counterpart to jQuery's click event handler

I'm trying to figure out how to achieve the same effect as this jQuery code. var divQuery = $('.html5gallery-thumbs-0').children(); divQuery.on('click', function () {...} I attempted it like this: var divQuery = document.g ...

Tabindex malfunction in Bootstrap dropdown menu when nested within a form and pressing Enter key

Within my form, I have integrated a Bootstrap 3 dropdown menu situated between two text input fields. The dropdown's role="menu" attribute allows for navigation using the up/down arrow and Enter keys. However, after making a selection in the dropdown ...

Struggling to pass Chai tests with Node and Express.js when trying to handle POST requests

Working through a Chai testing exercise and struggling to pass the POST route tests. Encountering two specific errors: 1) Todo API: POST /v1/todos Issue with creating and returning new todo using valid data: Header 'location' should ...

Pass an array from a script file in JavaScript to index.js within the Express framework

I've encountered a challenge in sending an array (or JSON object) from script.js to index.js, my express server file. I've explored various solutions such as passing the variable through an HTML file and then to another JavaScript file, utilizing ...

The greedy behavior of jquery UI is not behaving as expected

In my current project, I am attempting to place a diamond-shaped item into a droppable area which then generates two sub-droppables for additional items. However, I am facing difficulty implementing the "greedy" function with the newly generated droppables ...

When an array becomes empty, the interaction between v-for and v-if fails to function properly

Today I encountered a rather peculiar issue that I would like to share here: I noticed that when using v-for and v-if together with data value of [], it doesn't seem to work. For example: ts: [] <div v-for="t in ts" :key="t" v-if="ts.length"> ...

Using React.js to Retrieve Data from the Server without AJAX Calls

Currently, I am in the process of creating a web application using Express.js for the back-end and React.js for the front-end. Prior to using React.js, I utilized EJS templating and followed a similar workflow on the back-end as shown below: var express = ...

Mastering the art of writing protractor scenarios

In a hypothetical scenario where an Angular app consists of two pages - one for contacts (featuring a table with contacts and an "add new contact" button) and another for adding a new contact, the following steps can be outlined: Click on the "add" butto ...

Can this JSON object be created? If so, what is the process to do so?

Is it possible to create a JSON array with integers like the examples below? "data" : [ "1000": "1000", "1200": "1200", "1400": "1400", "1600": "1600", "1800": "1800", ] or "data" : [ 1000: 1000, 1 ...

Exploring the wonders of Node.js, Redis, and Express.js while navigating through the enchanting world of Asynchronous

Hello there, I must confess that this is a whole new realm for me... Here is what we've got: app.get('/user/:user_id/followings', function(req, res) { var response = {} , userId = req.params.user_id , ids = req.param(' ...