停止迭代并在两个数组之间找到匹配时返回true

时间:2018-01-16 14:31:40

标签: javascript arrays indexeddb pouchdb

我有两个数据集,一个在indexedDB中,一个在PouchDB中(是的,我知道PouchDB是indexedDB的一个实现)。

indexedDB中的一个是房间列表,通过上一页存储在indexedDB中,并显示在当前页面上。

PouchDB中的一个是房间审核员记录的房间使用情况日志。我想迭代第一个列表,并检查每个项目是否出现在审计房间列表中。如果确实出现了,我想设置一个标志来表示。

这是我的Javascript。 (我在浏览器中运行它并且它确实在进程中的某个时刻返回true,因为控制台日志输出显示了这一点,但是该标志没有针对列表项设置。)

我想知道它是否会继续循环审核记录并覆盖" true"值?

这是查询indexedDB并调用查询PouchDB的函数的函数:

function getRoomsInRoute() {
    var routeNumber = $.jStorage.get('currentRoute', '');
    var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;

    openRequest = window.indexedDB.open("rooms", 1);
    openRequest.onupgradeneeded = function() {
        var db = openRequest.result;
        var itemStore = db.createObjectStore("rooms", {keyPath: "room_id"});
        var index = itemStore.createIndex("rooms", ["route_number"]);
    };

    openRequest.onerror = function(event) {
        console.error(event);
    };

    openRequest.onsuccess = function (event) {
        var db = openRequest.result;
        db.onerror = function(event) {
            // Generic error handler for all errors targeted at this database's requests
            console.error(event.target);
            console.log("Database error: " + event.target.error.name || event.target.error || event.target.errorCode);
        };
        var transaction = db.transaction(['rooms'], "readwrite");
        var itemStore = transaction.objectStore("rooms");
        var index = itemStore.index("rooms", ["route_number"]);
        console.log('DB opened');
        var intRouteNumber = parseInt(routeNumber);
        //var range = IDBKeyRange.only(intRouteNumber);

        itemStore.openCursor().onsuccess = function(event) {
            var cursor = event.target.result;
            if(cursor) {
                var audited;
                if(cursor.value.route_number == routeNumber) {
                    if (checkIfAudited(cursor.value.room_seq)) {
                        var audited = ' <span class="checked"><i class="fa fa-check"></i></span>';
                    } else {
                        var audited = "";
                    }
                    $('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '.&nbsp;</small><a href="/static?action=edit&amp;room_id='+ cursor.value.room_id +'&amp;route_number='+ cursor.value.route_number +'&amp;sequence='+ cursor.value.room_seq +'&amp;roomname='+ cursor.value.room_name +'&amp;capacity='+ cursor.value.room_capacity +'">' + cursor.value.room_name + '</a>'+audited+'</li> ');
                }

                cursor.continue();
            } else {
                console.log('Entries all displayed.');
                if(!($.jStorage.get('reverseroute', ''))) {
                    reverseroute = 'asc';

                } else {
                    reverseroute = $.jStorage.get('reverseroute', '');
                }
                appendHref(reverseroute);
            }
        };

        // Close the db when the transaction is done
        transaction.oncomplete = function() {
            db.close();
        };
    };
}

这是查询PouchDB以查看它是否已被审核的函数:

function checkIfAudited(roomseq) {
    var today = new Date();
    if(is_BST(today) == true) {
        var currentHour = today.getHours()+1;
    } else {
        var currentHour = today.getHours();
    }
    var currentDay = today.getDate();
    var currentMonth = today.getMonth();

    options = {},
    that = this,
    pdb = new PouchDB('pouchroomusage');
    options.include_docs = true;
    var pouchOpts = {
      skipSetup: true
    };
    var opts = {live: true};

    pdb.allDocs(options, function (error, response) {
        response.rows.some(function(row){
            var auditTime = new Date(row.doc.timestamp);
            var auditHour = auditTime.getUTCHours();
            var auditDay = auditTime.getDate();
            var auditMonth = auditTime.getMonth();
            if(row.doc.sequence == roomseq && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth) {
                var isAudited = true;   
                console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay); 
                console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
            } else {
                var isAudited = false;
                console.log('No matches');
            }
            return isAudited;
        });
    });
}

我已经阅读了有关比较两个阵列的其他一些问题和答案。

我不知道如何使用for循环pdb.allDocs :(

以下是console.log的输出:

  

49没有比赛

     

RoomSeq:1;审计小时:14;当前小时:14; auditDay:16   currentDay:16; auditMonth:0; currentMonth:0; isAudited:true

     

2300没有比赛

那么如何在第二个函数到达PouchDB中的匹配记录时停止并返回true?

3 个答案:

答案 0 :(得分:1)

在我看来, pouchdb方法alldocs是异步的。 但是你以同步方式测试试听。因此,在返回checkIfAudited之后,将返回pdb.alldocs回调函数返回的内容。因此,checkIfAudited始终返回undefined

在我看来,您应该只在temStore.openCursor().onsuccess中创建一次pouchdb实例。然后,您需要在checkIfAudited函数中正确返回审计状态。

例如,您可以执行以下操作:

itemStore.openCursor().onsuccess = function(event) {

  var cursor = event.target.result;

  if (cursor) {

    if (cursor.value.route_number == routeNumber) {

      var audited;
      options = {},
      pdb = new PouchDB('pouchroomusage');
      options.include_docs = true;

      pdb.allDocs(options, function (error, allDocsResponse) {

        if (checkIfAudited(allDocsResponse, cursor.value.room_seq)) audited = ' <span class="checked"><i class="fa fa-check"></i></span>'

        else audited = "";

        $('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '.&nbsp;</small><a href="/static?action=edit&amp;room_id='+ cursor.value.room_id +'&amp;route_number='+ cursor.value.route_number +'&amp;sequence='+ cursor.value.room_seq +'&amp;roomname='+ cursor.value.room_name +'&amp;capacity='+ cursor.value.room_capacity +'">' + cursor.value.room_name + '</a>'+audited+'</li> ');

      });

    };

    cursor.continue();

  } else {

    console.log('Entries all displayed.');

    if(!($.jStorage.get('reverseroute', ''))) reverseroute = 'asc'

    else reverseroute = $.jStorage.get('reverseroute', '');

    appendHref(reverseroute);

  };


};

对于checkIfAudited:

function checkIfAudited(allDocs, roomseq) {


    var today = new Date();
    if(is_BST(today) == true) {
        var currentHour = today.getHours()+1;
    } else {
        var currentHour = today.getHours();
    }
    var currentDay = today.getDate();
    var currentMonth = today.getMonth();

    for (i=0; i<allDocs.rows.length; i++) {
      var row = allDocs.rows[i];

      var auditTime = new Date(row.doc.timestamp);
      var auditHour = auditTime.getUTCHours();
      var auditDay = auditTime.getDate();
      var auditMonth = auditTime.getMonth();
      if(row.doc.sequence == roomseq && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth) {
        console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay); 
        console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
        return true;    ///// <---- return that it is audited
      } else {
        console.log('No matches');
      };

    });

    return false    ///// <---- return false if no iteration has matched
}

答案 1 :(得分:1)

首先,我不会过于喜欢利用Array.prototype.some的短路行为。使用您可以使用的本机功能。 indexedDB提供了一种内置的方法来停止推进游标,或者只从商店中加载有限数量的对象。

其次,当您只对几个对象感兴趣时,您可能希望避免从商店加载所有对象。使用光标走路商店。由于您似乎想要在满足某些条件时停止迭代,因此只需在此时不要调用cursor.continue。

第三,即使决定首先从商店加载所有对象,使用for循环比利用some要好得多。通过利用我的意思是以不同于预期的方式使用该功能。我敢打赌,如果你恢复使用带有break语句的for循环,代码将更清晰,因此更容易理解为什么循环不会在你预期的时候中断。

第四,我是否会花时间将indexedDB查询的结果附加到中间数据结构(如数组),而不是立即与DOM交互。它将更多地分开,你会发现代码更容易调试。

第五,在与indexedDB混合使用异步调用时应该非常小心。当你将调用交错到其他promises时,indexedDB就会出现问题。

答案 2 :(得分:0)

这是经过多次调整后我最终得到的结果。

现在每<span class="checked"><i class="fa fa-check"></i></span>次增加<li>次,但至少会增加<li>次。

所以我对CSS做了一点点破解,只显示一个span.checked

.checked {
    color: #fff;
    background-color: #006338;
    border-radius: 50%;
    padding: 2px 3px;
}

/* only display the first instance of checked */
li > span.checked ~ .checked {
    display: none;
}

(我还在我的脚本中发现并修复了另一个错误,我没有设置route_numberroom_id。)

function getRoomsInRoute() {
    var routeNumber = $.jStorage.get('currentRoute', '');
    var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;

    openRequest = window.indexedDB.open("rooms", 1);
    openRequest.onupgradeneeded = function() {
        var db = openRequest.result;
        var itemStore = db.createObjectStore("rooms", {keyPath: "room_id"});
        var index = itemStore.createIndex("rooms", ["route_number"]);
    };

    openRequest.onerror = function(event) {
        console.error(event);
    };

    openRequest.onsuccess = function (event) {
        var db = openRequest.result;
        db.onerror = function(event) {
            // Generic error handler for all errors targeted at this database's requests
            console.error(event.target);
            console.log("Database error: " + event.target.error.name || event.target.error || event.target.errorCode);
        };
        var transaction = db.transaction(['rooms'], "readwrite");
        var itemStore = transaction.objectStore("rooms");
        var index = itemStore.index("rooms", ["route_number"]);
        console.log('DB opened');
        var intRouteNumber = parseInt(routeNumber);
        //var range = IDBKeyRange.only(intRouteNumber);

        itemStore.openCursor().onsuccess = function(event) {
            var cursor = event.target.result;
            var audited = "";
            if(cursor) {
              if(cursor.value.route_number == routeNumber) {

                $('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '.&nbsp;</small><a href="/static?action=edit&amp;room_id='+ cursor.value.room_id +'&amp;route_number='+ cursor.value.route_number +'&amp;sequence='+ cursor.value.room_seq +'&amp;roomname='+ cursor.value.room_name +'&amp;capacity='+ cursor.value.room_capacity +'">' + cursor.value.room_name + '</a></li> ');


              }

              cursor.continue();

            } else {
                console.log('Entries all displayed.');
                if(!($.jStorage.get('reverseroute', ''))) {
                    reverseroute = 'asc';
                } else {
                    reverseroute = $.jStorage.get('reverseroute', '');
                }
                appendHref(reverseroute);

                asyncCallToPouchDb();
            }
        };


        // Close the db when the transaction is done
        transaction.oncomplete = function() {
            db.close();
        };
    };
}


function asyncCallToPouchDb() { 
    $('#mylist li').each(function(){
        var audited = "";
        var room_id = $(this).attr('id');
        var thisLi = $(this);
        audited = callPouchDb(room_id, thisLi);

    });
}


function callPouchDb(room_id, thisLi) {
    options = {},
    pdb = new PouchDB('pouchroomusage');
    options.include_docs = true;
    var audited = "";
    //return new Promise(resolve => {
         pdb.allDocs(options, function (error, response) {
            result = response.rows;
            for (i = 0; i < result.length; i++) { 
                if (checkIfAudited(result[i], room_id)) {
                    audited = ' <span class="checked"><i class="fa fa-check"></i></span>';
                } 
                thisLi.append(audited);
            } 
            //thisLi.append(audited);
            /*end pdb.allDocs*/
        }).then(function (result) {

          // handle result
          console.log(result);

        }).catch(function (err) {
          console.log(err);
        });

    // });

}

function checkIfAudited(row, room_id) {

    var today = new Date();
    if(is_BST(today) == true) {
        var currentHour = today.getHours()+1;
    } else {
        var currentHour = today.getHours();
    }
    var currentDay = today.getDate();
    var currentMonth = today.getMonth();
    var currentYear = today.getYear();

    var isAudited = false;    ///// <---- define isAudited outside of db iteration scope

      var auditTime = new Date(row.doc.timestamp);
      var auditHour = auditTime.getUTCHours();
      var auditDay = auditTime.getDate();
      var auditMonth = auditTime.getMonth();
      var auditYear = auditTime.getYear();
      if(row.doc.room_id == room_id && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth && currentYear == auditYear) {
        isAudited = true;   
        // debug 
   //     console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay); 
   //     console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
      } else {
         console.log('No matches');
      };

    return isAudited 
}