A simultaneidade em JS é fácil: com Promises.

Promessas são uma forma de representar valores eventuais. Eles diferem do estilo de passagem de continuação (também conhecido como Callbacks, Callbacks Everywhere) porque fornecem valores reais que você pode manter, compor, abstrair e desacoplar em seu código – então é mais fácil.

Esta é uma continuação do meu comentário neste protocolo: https://coderwall.com/p/ineqig

1) Promessas representam valores eventuais

var pinky = require('pinky')
var fs = require('fs')

// You just return a placeholder for your value,
// then fulfill or reject your placeholder
// depending on the asynchronous operation later on
function read(filename) {
var promise = pinky()
fs
.readFile(filename, function(error, buffer) {
if (error) promise.reject(error)
else promise.fulfill(buffer)
})
return promise
}

2) Promessas compostas

– Porque eles são valores reais, como sua String ou Array:

function decode(encoding, buffer) {
// We put things into a Promise, so we can
// accept both real buffers *and* eventual ones :D
return pinky(buffer).then(function(buffer){
return buffer.toString(encoding)
})
}
var data = decode('utf-8', read('foo.txt'))

3) As promessas podem ser abstraídas

– porque são valores!

// This means we can make any function
// accept a promise without changing any
// of its code :D
function lift2(a, b, f) {
return pinky(a).then(function(valueA) {
return pinky(b).then(function(valueB) {
return pinky(f(valueA, valueB))
})
})
})
function concat(a, b) { return a + b }
var fooBar = lift2(data, fs.readFileSync('bar.txt', 'utf-8'), concat)

4) É fácil criar novos combinadores

– Todas as propriedades acima tornam isso mais fácil.

Bônus: desacopla todo o seu código emaranhado!

function pipeline(fns) {
return fns.reduce(function(promise, f){
return promise.then(f)
}, promise(undefined) }
}
// This looks better with currying, but you
// can use `.bind(null, x, y)`
pipeline
( read('foo.txt')
, decode('utf-8')
, splitLines
, map(toUpperCase)
, joinLines
, write('screaming.txt'))

// Or in parallel
parallel
( read('foo.txt')
, read('bar.txt')
, read('baz.txt'))
.then(function(foo, bar, baz) {
return foo + ';' + bar + ';' + baz
})

// Or in any other order you want, just
// build relationships between
// the values using `.then()` and the
// promise library will figure it out :D

5) As promessas são padrão

Portanto, escolha qualquer biblioteca desejada e você poderá trabalhar com qualquer código assíncrono. Além disso, se você escrever um combinador para promessas, ele funciona para todas as bibliotecas de promessas e tudo que usa promessas, consulte: https://github.com/killdream/pinky-combinators

6) Trabalhar com callbacks de estilo de nó é um acéfalo

Se você estiver no Node, pode criar um combinador que transforma o estilo do Node no estilo da promessa em 5 linhas de código, mas eu já escrevi um para você: https://github.com/killdream/pinky-for-fun /blob/master/src/index.ls#L42-L51

Referências e leituras adicionais

Certifique-se de verificar a especificação ( https://github.com/promises-aplus/promises-spec ) e a lista de implementações em conformidade ( https://github.com/promises-aplus/promises-spec/blob/master/ implementations.md )

Grandes descrições sobre o assunto incluem a postagem de James Coglan ( http://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-promises-are-functional-nodes-biggest-missed-opportunity/ ), e a postagem de Irkali HisSurnameIsTooDifficultToSpell ( http://jeditoolkit.com/2012/04/26/code-logic-not-mechanics.html#post )