2012-05-23 7 views
1

на асинхронном программировании, мы используем много обратных вызовов, например:Может ли javascript комбинировать асинхронный код в одну функцию?

var running = function(){ 
    do_sth(); 
    $.post("/xxx", function(data){ 
     do_sth2(); 
     $.get("/ttt", function(data){ 
      do_sth3(); 
     } 
    } 
} 

, и я думаю, что все должно быть так:

var running = do_async(function(){ 
    do_sth(); 
    var data = $.post("/xxx"); 
    do_sth2(); 
    data = $.get("/ttt"); 
    do_sth3(); 
}); 

Как я могу это сделать?

и есть проект на этом: https://github.com/JeffreyZhao/jscex

, и я думаю, что этот проект не так прост в использовании (реализация с помощью синтаксического анализа исходного кода)

может быть, в будущем, у нас есть родные Поддержка javascript?


Я сделал некоторые исследования по этому вопросу, нашел disscussion и библиотеку здесь для справки:

https://github.com/JeffreyZhao/jscex

Defer CoffeeScript https://github.com/jashkenas/coffee-script/issues/350

сливаются в CoffeeScript: https://github.com/jashkenas/coffee-script/issues/350

библиотека tamejs http://tamejs.org/

stratifiedjs http://onilabs.com/stratifiedjs

Kaffeine http://weepy.github.com/kaffeine/

вики страница об этом: http://en.wikipedia.org/wiki/Continuation-passing_style


Это не очень легко добавить библиотеку, чтобы поддержать его,

Возможно, в будущем javascript добавит ключевое слово «defer».


же вопрос: Pattern for wrapping an Asynchronous JavaScript function to make it synchronous

+0

Если вы хотите, чтобы выполнение приостанавливалось до тех пор, пока не завершится выполнение '$ .post()' (или другой функции async), это будет _synchronous_ code, а не _async_. (Что вы делаете, но на самом деле не должны этого делать.) Изучили ли вы использование [отложенной функциональности jQuery] (http://api.jquery.com/category/deferred-object/), которая, по крайней мере, позволила бы вам структурировать ваши код немного по-другому, если не совсем так, как вы хотите? – nnnnnn

+0

Я думаю, что Jscex прост в использовании. Он основан на технологии компиляции, но предназначен для того, чтобы быть прозрачным для пользователя. Не могли бы вы рассказать мне об этом проекте? –

ответ

1

Callbacks являются жизненно важной частью JavaScript. Javascript предназначен для их использования. Я не думаю, что мы когда-нибудь получим какой-то «синхронизатор». Напротив, мы получаем все больше и больше инструментов, чтобы делать асинхронно, например Worker.

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

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

+0

Обратный вызов - это инстинкт счетчика, его непросто программировать/отлаживать/понимать, – linjunhalida

+0

Я использую его в lisp, а в js, обратные вызовы напоминают мне об этом, я могу запрограммировать этот путь, но я думаю, что это проблема. – linjunhalida

1

Возможно, вы можете взглянуть на Promises. Имеются некоторые варианты реализации, см. commonjs.org.Все они позволяют цепочки, так что вы можете написать код следующим образом:

function running(){ 
    return do_sth() 
     .then($.post.bind($, "/xxx")) 
     .then(do_sth2) 
     .then($.get.bind($, "/ttt")) 
     .then(do_sth3); 
    // returns a Promise to run all these tasks 
    // ...or: a Promise for the result of the last of the chained tasks 
} 

Если вы используете JQuery, это уже встроенный с deferred functionality (не моей любимой реализации Promise, хотя):

function running(){ 
    do_sth(); 
    return $.post("/xxx") 
     .then(do_sth2) 
     .then(function(){ 
     $.get("/ttt") 
      .then(do_sth3); 
     }); 
} 
+0

jquery теперь имеет это с отсрочками. –

+0

круто! ............. – linjunhalida

1

Я уверен, что вы цените, что это поведение асинхронного обратного вызова по дизайну, а не какой-то неудачный надзор. Это довольно много происходит в сообществе Node.js (Node использует аналогичный цикл событий), и там был разработан ряд альтернатив на основе волокон, потоков и т. Д. Несколько недавних обсуждений - here и here, которые также охватывают ряд этих альтернатив.

Edit:Another topic на асинхронных библиотеки на форуме узла, включая обсуждение

  • async - поток управления асинхронного, некоторый функционал сахар
  • after - поток управления асинхронного, некоторый функционал сахар
  • step - простой контроль потока

Некоторые из авторов писали эти/написали другие библиотеки управления потоками, и я определенно счел это заслуживающим внимания.

Другой материал, который я недавно прочитал

Я не уверен, что это маршрут, который я бы спустил, однако, unle ss, у вас есть определенная потребность в таком поведении (например, в браузере, о котором упоминал @MaxArt, или ваш код очень хорошо подходит для многопоточной (и т. д.) модели), поскольку большинство из этих решений на самом деле однопоточные петли под ним. Вы можете избежать слишком много неприятного вложения путем передачи/вызова названных функций, например.

function a() { 
    somethingAsync(function (val) { b(val); }); 
} 

function b(val) { ... } 
+0

Да, я использую этот метод в своем коде сейчас, и я надеюсь, что есть лучший способ сделать это. – linjunhalida

+0

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

+0

Прочитайте еще кое-что по этой теме недавно и подумал, что я добавлю его здесь, в надежде, что это тоже полезно для других. (Привет, другие читают!) – meloncholy

0

Поскольку JavaScript полностью однопоточен, абсолютно невозможно синхронизировать асинхронный код.

Я рекомендую вам практиковать, чтобы получить повесить вещи. Возможно, вы можете попробовать функцию setTimeout. Дайте ему обратный вызов и, возможно, он отобразит "Hello, World!" на консоли. А также, передайте число 0 в качестве последнего параметра.

С учетом сказанного, однако, вы можете «прикрыть» асинхронный код с помощью библиотек.

Существует, в частности, мой любимый. Он называется async.js. Я использую его все время, чтобы поддерживать глубоко вложенные асинхронные вызовы, которые выглядят более синхронно (т. Е. Запросы MongoDB).

async.waterfall([ 

    // Call to the first asynchronous call... 
    function (callback) { 
    setTimeout(function() { 
     callback(null, "Hello, World!"); 
    }, 0); 
    }, 

    // That needs to make another... 
    function (callback, message) { 
    console.log(message); 
    setTimeout(function() { 
     callback(null, "It's a nice day!"); 
    }, 0); 
    }, 

    // Another... 
    function (callback, message) { 
    console.log(message); 
    setTimeout(function() { 
     callback(null, "Bye, now!"); 
    }, 0); 
    }, 

    // And another. 
    function (callback, message) { 
    console.log(message); 
    } 

]); 

// Without making the entire thing hopelessly nested deeply. 
Смежные вопросы