سؤال

أنا أعمل على القليل من JavaScript الذي يتفاعل مع قاعدة بيانات SQLite من جانب العميل ، عبر Newish window.openDatabase(...), database.transaction(...) وواجهة برمجة التطبيقات ذات الصلة. كما يعلم معظمكم عندما تقوم بتنفيذ استعلام بهذه الطريقة ، فهي مكالمة غير متزامنة ، وهي عادة جيدة. يمكنك إجراء المكالمة والتعامل مع النتائج حسب الاقتضاء مع عمليات الاسترجاعات.

في وضعي الحالي ، أعمل على Algo لعميل يقوم ببعض التسلسل الهرمي الذي يمشي في قاعدة البيانات المخزنة محليًا. يتطلب جزء algo الذي أواجه مشكلة في البدء في صف واحد ، والذي يحتوي على إشارة إلى "الوالد" (حسب المعرف) وهو صف آخر في الجدول. لا بد لي من الاستمرار في المشي هذه الشجرة حتى أصل إلى الجذر.

المشكلة هي أنني في مرحلة لست متأكدًا من كيفية استخدام استعلام غير متزامن مع رد اتصال للاستمرار في تغذية معرفات الأصل الحلقة. من الناحية المثالية ، يمكنني الحصول على الاستعلام لحظره حتى أتمكن من فعل كل شيء في الحلقة. إليك الأجزاء الرئيسية لإعداداتي الحالية:

    for (i in search.searchResults.resultsArray)
    {
        hierarchyArr = new Array();
        pageHierarchyArr = new Array();
        id = search.searchResults.resultsArray[i].ID;

        while (id != null && id != "")
        {
            var hierarchySql = "SELECT ID, parentID, type, content FROM content WHERE ID = " + id;

            // This is a prettied up call to database.transaction(...)
            var rs = db.getRS(hierarchySql);

            // Ideally the code below doesn't execute until rs is populated

            hierarchyArr.push(rs[0]);

            if (rs[0].type == "page")
            {
                pageHierarchyArr.push(rs[0]);

                // Do some additional work
            }

            id = rs[0].parentID;
        }
    }

كما قد تتخيل ، لا يعمل بشكل جيد. يحصل التسلسل الهرمي على "غير محدد" يتم دفعه إليه ، ثم ينهار البرنامج النصي عندما يحاول التحقق من نوع RS [0].

عندما أحاول إعداده باستخدام رد الاتصال (db.getRSAndCallback(sql, callbackFunc), ، الذي استخدمته في الاستعلامات السابقة غير المعتمدة على ما يرام) ، إنه أسوأ: الحلقة الداخلية تقلع مثل الجنون لأن ID لم يتم تحديثه ؛ من المفترض أن الحلقة تحافظ على مترجم جافا سكريبت مشغول لدرجة أنه لا يملأ أبدًا rs. في بعض الاختبارات الاصطناعية حيث أجبرت الحلقة الداخلية على كسر بعد بضع تكرارات بدأت جميع عمليات الاسترجاعات في النهاية في النهاية ، بعد انتهاء الحلقة.

"المعيار" (كما هو الآن) في http://dev.w3.org/html5/webdatabase/#synchronous-database-api يبدو أنه يشير إلى وجود واجهة برمجة تطبيقات متزامنة ، لكنني لم أر أي علامة على أي متصفحات قائمة على الويب.

هل يمكن لأي شخص تقديم اقتراحات حول كيف يمكنني أيضًا. قم بصياغة هذه الاستعلامات التكرارية المترابطة بشكل صحيح باستخدام عمليات الاسترجاعات أو ب. احصل على المكالمة بطريقة ما لتدوم فعليًا بطريقة متزامنة أو متزامنة على ما يبدو.

شكرا جزيلا مقدمًا لأي شخص يأخذ صدعًا في هذه المشكلة الصغيرة الصعبة على ما يبدو.

نايم

ملاحظة: إليك تنفيذ العميل لـ db.getRS كمرجع:

.
.
.
getRS: function(sql)
{
    var output = [];
    db.database.transaction(function(tx)
    {
        tx.executeSql(sql, [], function(tx,rs)
        {
            for(i = 0; i < rs.rows.length; i++)
            {
                output.push(rs.rows.item(i));
            }
        },
        function(tx, error) { ... }
    )});
    return output;
},
.
.
.
هل كانت مفيدة؟

المحلول

لقد استخدمت عمليات الاسترجاعات والإغلاق لحل مشكلة مماثلة ، ضع في اعتبارك:

function getFolder(id, callback) {
var data = [];
ldb.transaction(function (tx) {
tx.executeSql('SELECT * FROM folders where id=?',
    [id],
    function (tx, results) {
        if (results.rows && results.rows.length) {
            for (i = 0; i < results.rows.length; i++) {
                data.push(results.rows.item(i));
            }
        }
        if (typeof(callback) == 'function')
            callback(data);
    },
    function (tx, error) {
        console.log(error);
    });
});
}

في استمرار هذا المثال ، يحتوي المجلد على خاصية الأبوين لتحديد علاقةها بالمجلدات الأخرى. كما يفعل وثيقة. ما يلي سيحصل على مسار المستند باستخدام الإغلاق (النجاح):

  function getDocPath(doc, callback) {
      var path = [];
      var parent = doc.parent;
      var success = function(folder) {
         var folder = folder[0];
         parent = folder.parent;
         path.push({'id':folder.id,'name':folder.name});
         if (parent != "undefined")
             getFolder(parent, success);
         else
             if ( typeof(callback) == 'function' ) callback(path.reverse());
      }
      getFolder(parent, success);
  }

نصائح أخرى

يمكنك استخدام عمليات الاسترجاعات مع إغلاق إلى مجموعتك من الاستعلامات المتبقية. أو يمكنك استخدام العودية ، وتمرير المكدس كمعلمات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top