Подтвердить что ты не робот

Шаблон для упаковки функции асинхронного JavaScript, чтобы сделать ее синхронной

Я работаю с JavaScript API, где большинство функций асинхронны. API представляет собой API базы данных JavaScript WebKit, который является связующим звеном с подмножеством функциональных возможностей для управления базами данных SQLite3. Я понимаю, что дизайнерское решение делает вещи асинхронными, чтобы не блокировать и не обеспечивать гибкий пользовательский интерфейс. В моей ситуации я знаю, что мое использование вызовов асинхронного API будет выполняться быстро. Поскольку это так, я хотел бы предоставить моим разработчикам более чистый и простой в использовании API-интерфейс оболочки, который заставляет синхронные вызовы.

Здесь асинхронный вызов

db.executeSql(sqlStatement, function(result) {
  // do something with result
});

И вот что я хотел бы сделать

var result = dbWrapper.executeSql(sqlStatement);
// do something with result

Есть ли шаблон дизайна/способ сделать это? Предпочтительным является пример, написанный или связанный с кодом. Целевой платформой/браузером является Mobile Safari на iPhone.

Спасибо

4b9b3361

Ответ 1

Извините, JavaScript не предоставляет примитивы языка (например, потоки или сопрограммы), чтобы асинхронные действия выполнялись синхронно или наоборот.

Как правило, вы получаете только один поток выполнения, поэтому вы не можете получить обратный вызов из таймера или XMLHttpRequest readystatechange до тех пор, пока стек вызовов, ведущих к созданию запроса, не будет полностью распущен.

Короче говоря, вы не можете этого сделать; подход с вложенными замыканиями на странице WebKit, с которой вы связаны, является единственным способом, который я знаю, чтобы сделать код читаемым в этой ситуации.

*: за исключением некоторых неясных ситуаций, которые не помогут вам и обычно считаются ошибками

Ответ 2

StratifiedJS позволяет делать именно это.

Там даже статья о том, как применить ее в хранилище браузера: http://onilabs.com/blog/stratifying-asynchronous-storage

И это библиотека Stratified JavaScript, в которой используется https://gist.github.com/613526

Пример выглядит следующим образом:

var db = require("webdatabase").openDatabase("CandyDB", ...);
try {
  var kids = db.executeSql("SELECT * FROM kids").rows;
  db.executeSql("INSERT INTO kids (name) VALUES (:name);", [kids[0]]);
  alert("done");
} catch(e) {
  alert("something went wrong");
}

может быть, немного поздно, но техника не существовала тогда;)

Ответ 3

Вы можете попробовать что-то вроде:

function synch()
{
    var done = false;
    var returnVal = undefined;

    // asynch takes a callback method
    // that is called when done
    asynch(function(data) {
        returnVal = data;
        done = true;
    });

    while (done == false) {};
    return returnVal;
}

Но это может заморозить ваш браузер на время асинхронного метода...

Или взгляните на описательный JavaScript: описательный JavaScript - небольшое расширение языка JavaScript, которое позволяет блокировать возможности для асинхронных обратных вызовов событий. Это делает асинхронный код обновляемым и понятным.

http://neilmix.com/narrativejs/doc/index.html

Mike

Ответ 4

если вы используете jQuery Ajax:  $.ajax()

вы можете установить для атрибута asynch значение false, и тогда у вас будет запрос на синхронизацию ajax на сервер.

Ответ 5

Мы используем GWT RPC, который также имеет асинхронный API. Решение, которое мы в настоящее время используем для выполнения нескольких асинхронных вызовов в последовательном порядке, - это цепочка вызовов:

callA(function(resultA) {
    callB(resultA, function(resultB) {
        callC(); //etc.
    });
});

Этот вложенный подход обеспечивает то, что вы хотите, но оно многословно и трудно читается для новичков. Один из подходов, которые мы исследовали, - это добавление вызовов, которые нужно сделать в стек, и их выполнение в следующем порядке:

callStack = [
    callA(),
    callB(),
    callC()
];

callStack.execute();

Тогда столбец управления:

  • Вызов вызовов в последовательном порядке (например, проводка в первом примере)
  • Передача результата от одного вызова к следующему.

Однако, поскольку Java не имеет ссылок на функции, каждый вызов в стеке вызовов потребует анонимного класса, поэтому мы не можем отказаться от такого решения. Однако у вас может быть больше успеха в javascript.

Удачи!

Ответ 6

Это фактически не реализует синхронную работу с db-запросом, но это было моим решением для простого управления. В основном используйте вызывающую функцию как функцию обратного вызова и проверяйте аргумент результатов. Если функция получает результаты, она анализирует их, если нет, она отправляет себя как обратный вызов методу запроса.

 render: function(queryResults){
  if (typeof queryResults != 'undefined'){
   console.log('Query completed!');
   //do what you will with the results (check for query errors here)

  } else {
   console.log('Beginning query...');
   this.db.read(this.render); //db.read is my wrapper method for the sql db, and I'm sending this render method as the callback.
  }
 }

Ответ 7

Я не уверен, что это подходящее место, но я здесь ищу работу для ответов на синхронные звонки в Firefox. решением было бы удалить обратный вызов onreadystatechange и выполнить прямой вызов. Это то, что я нашел, и мое решение синхронный вызов с сервисом отдыха