2015-03-17 9 views
10

Sto ancora imparando JavaScript Promise s, e mi sono imbattuto in un comportamento che non capisco.Promessa JavaScript quindi() che ordina

var o = $("#output"); 
 
var w = function(s) { 
 
    o.append(s + "<br />"); 
 
} 
 

 
var p = Promise.resolve().then(function() { 
 
    w(0); 
 
}).then(function() { 
 
    w(1); 
 
}); 
 

 
p.then(function() { 
 
    w(2); 
 
    return new Promise(function(r) { 
 
     w(3); 
 
     r(); 
 
    }).then(function() { 
 
     w(4); 
 
    }); 
 
}).then(function() { 
 
    w(5); 
 
}); 
 

 
p.then(function() { 
 
    w(6); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="output"></div>

mi aspetterei queste istruzioni da eseguire in ordine - cioè, il che la produzione sarebbe

0 
1 
2 
3 
4 
5 
6 

Invece, l'uscita è

0 
1 
2 
3 
6 
4 
5 

Anche la rimozione dell'interno di Promise dà s, quello che mi sembra di essere, contraddire i risultati. 1 viene emesso prima di 2, ma 6 viene emesso prima di 5.

Qualcuno può spiegarmi questo?

Qualcosa che ho notato è che la riassegnazione di p ogni volta ci dà l'ordine che mi aspetterei.

+0

Perché ti aspetti quell'ordine? L'ordine in cui scrivi il codice non è necessariamente l'ordine in cui le promesse si risolvono; solo "allora" ha il controllo su questo. – elclanrs

+0

Perché mi aspetto che 'then()' s accada in ordine. – dfoverdx

+1

Sì, il 'then' s di ** ogni ** catena di promesse. – elclanrs

risposta

24

La ragione che si vede 6 è presto perché non l'hai fatto a catena, è ramificata.

Quando si chiama p.then().then().then(), si ha una serie di promesse che devono eseguire nell'ordine corretto.
Tuttavia, se chiami p.then().then(); p.then(), hai 2 promesse in allegato a p - essenzialmente creando un ramo e il secondo ramo verrà eseguito insieme al primo.

È possibile risolvere questo problema assicurando li concatenare p = p.then().then(); p.then();

FYI, è quasi mai voglia di espandersi, a meno che non li portano di nuovo insieme (ad es. Promise.all), o sono intenzionalmente la creazione di un "fuoco e dimentica" ramo.

4

Cosa fa r()?

L'ordine è indeterminato perché si sta facendo la stessa promessa -> questo si riferisce specificamente alla seconda e alla terza catena.

Se si stava facendo quanto segue, quindi ordine può essere garantito:

var p = Promise.resolve().then(function() { 
    w(0); 
}).then(function() { 
    w(1); 
}); 

// Key difference, continuing the promise chain "correctly". 
p = p.then(function() { 
    w(2); 
    return new Promise(function(r) { 
     w(3); 
     r(); 
    }).then(function() { 
     w(4); 
    }); 
}).then(function() { 
    w(5); 
}); 

p.then(function() { 
    w(6); 
}); 
+0

'r()' è solo la funzione 'resolve()' di Promise interiore. Quindi sto comprendendo correttamente, che 'var p = Promise.resolve(); p.then (f1); p.then (f2); 'significa che' f1() 'e' f2() 'saranno ordinati, tuttavia il motore JS si sente come se fosse? – dfoverdx

+1

@dfoverdx: Sì, 'p.then (f); p.then (g) 'non è lo stesso di p.then (f) .then (g)'. – elclanrs

+0

Ok, ho capito. Grazie! – dfoverdx

Problemi correlati