2014-11-25 3 views
1

Я хочу использовать рекурсивную функцию, но каждая функция должна запускаться после завершения предварительной работы. поэтому я пишу этот код:Рекурсивная функция с отсрочкой

var service = ['users', 'news'], 
    lastSync = { 
       'users' : false, 
       'news' : false 
       }; 
db.transaction(function (tx) { 
    lastSyncFunc(tx,service,0).then(function(){ 
     console.log(lastSync); 
    }); 
}); 

function lastSyncFunc(tx,service,index){ 
    deferred = $q.defer(); 
    tx.executeSql("SELECT time FROM last_sync WHERE fService = ? ORDER BY id DESC LIMIT 1", [service[index]], function (tx, result) { 
     if (result.rows.length > 0) { 
      lastSync[service[index]] = result.rows.item(0).fTime; 
     } 
     return ++index<service.length ? lastSyncFunc(tx,service,index) : deferred.resolve(); 
    }); 
    return deferred.promise; 
} 

теперь моя программа возвращения false для lastSync.users и lastSync.users, потому что запустить этот раздел перед функцией полного запуска.

+0

Вы не можете «вернуть» из обратного вызова 'executeSql'. Правильно абстрагироваться от обратных вызовов и использовать обещания, прежде чем переходить к процедурам, специфичным для приложения, таким как рекурсивный вызов. – Bergi

ответ

2

попробовать что-то вроде этого:

function lastSyncFunc(tx,service,index, def){ 
    var deferred = def || $q.defer(); 
    tx.executeSql(
    "SELECT time FROM last_sync WHERE fService = ? ORDER BY id DESC LIMIT 1", 
    [service[index]], 
    function (tx, result) { 
     if (result.rows.length > 0) { 
      lastSync[service[index]] = result.rows.item(0).fTime; 
     } 
     return ++index<service.length ? 
     lastSyncFunc(tx,service,index, deferred) : 
     deferred.resolve(); 
    }); 
    return deferred.promise; 
} 

Я просто обеспечить отложенное до maxdepth, где мы можем разрешить его.

+0

Спасибо, братан: *, работал для меня :) – MajAfy

+0

Я никогда не работал с отложенным, может быть, это решение не «лучшие оценки»;) –

1

de facto Способ для этого заключается в том, чтобы избежать рекурсии, как описано here под заголовком «Коллекция Kerfuffle».

Защищенный шаблон может быть закодирован всем, что находится внутри структуры db.transaction(function() {...}), но более ясно вытащить tx.executeSql(...) и обещать его в отдельной функции.

Вы будете в конечном итоге с чем-то вроде этого:

var service = ['users', 'news'], 
    lastSync = { 
     'users' : false, 
     'news' : false 
    }; 
db.transaction(function (tx) { 
    return service.reduce(function(promise, serviceItem) { 
     return promise.then(function() { 
      return executeSqlPromisified(tx, serviceItem).then(function(fTime) { 
       if(fTime !== null) { 
        lastSync[serviceItem] = fTime; 
       } 
      }); 
     }); 
    }, $q.when(null)).then(function() { 
     console.log(lastSync); 
    }); 
}); 

function executeSqlPromisified(tx, serviceItem) { 
    var deferred = $q.defer(); 
    tx.executeSql("SELECT time FROM last_sync WHERE fService = ? ORDER BY id DESC LIMIT 1", [serviceItem], function (tx, result) { 
     if (result.rows.length) { 
      deferred.resolve(result.rows.item(0).fTime); 
     } else { 
      deferred.resolve(null); 
     } 
    }); 
    return deferred.promise; 
} 

для неопытного глаза, это будет очень хорошо нечитаемым, но поверьте мне, вы можете привыкнуть к этой модели.

+0

Спасибо за ответ, что такое 'serviceItem'? потому что у нас нет 'serviceItem' в наших переменных. и как «сервис» будет увеличиваться? – MajAfy

+0

Когда я запускаю этот код, я получаю ошибку, ошибка: 'Uncaught TypeError: Невозможно прочитать свойство 'then' of undefined' on line 'return prom.then (function() {' – MajAfy

+0

'serviceItem' является просто элементом' service' array, то есть то, что называется «service [index]» в коде в вопросе, то есть «пользователи», а затем «новости». 'service' повторяется конструкцией' service.reduce (...) ' . '.reduce()' - стандартный метод массива javascript. –