2016-03-30 5 views
1

Ich stieß auf einen Fehler in meinem Code, der mich lange Zeit verwirrte und nach einer Klärung suchte.Understanding .then() ES6

In diesem Code verursachte das auskommentierte innere Versprechen ein Problem. Das Promise.all() am Ende wurde fortgesetzt, sobald setTimeout aktiv war, nicht nach der Auflösung innerhalb des Timeouts.

Wrapping der asynchronen Code mit einer Verheißung behebt das Strömungsproblem, aber warum ist das?

Im Wesentlichen, warum können wir nicht einfach normalen Async-Code in einer. Then() - Kette, eine Rückkehr eine Promise.resolve() am Ende des asynchronen Rückrufs ausführen?

var asyncPromise = function() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { 
      console.log('Async Promise done'); 
      resolve(); 
     }, 1000); 
    }); 
}; 

var generateSignupPromises = function(qty) { 
    var promiseArray = []; 
    for (var i = 1; i <= qty; i++) { 
     promiseArray.push(
      function() { 
       return asyncPromise() 
       .then(function() { 
        console.log('Before Timeout'); 

        //Uncommenting this fixes the issue 
        //return new Promise(function(resolve, reject) { 
         setTimeout(function() { 
          console.log('After Timeout'); 
          //resolve(); 
          return Promise.resolve(); 
         }, 500); 
        //}) 
       }); 
      } 
     ); 
    } 
    return promiseArray; 
}; 

var test = generateSignupPromises(1); 

Promise.all([test[0]()]) 
.then(function() { 
    console.log('Done'); 
}); 

Link zum Ausführen von Code: http://www.es6fiddle.net/imfdtuxc/

+4

Ich kann nicht wirklich sagen, was Sie zu tun versuchen , aber eine 'return' in einem' setTimeout() '- Handler macht praktisch nie viel Sinn; Nichts wird auf den zurückgegebenen Wert achten. – Pointy

+2

Pyramide des Schicksals + Fülle anonymer Funktionen = unlesbarer Code + unerwartetes Verhalten. – Amit

+1

setTimeout ist nicht asynchron. Es wird synchron zurückgegeben, was dazu führt, dass then() undefined und "promise" zurückgibt. Durch das Hinzufügen Ihrer zusätzlichen Zeile wird ein weiteres Versprechen zurückgegeben, das bis zur Auflösung wartet. Übrigens. Dies ist nicht, wie Versprechen verwendet werden sollten. – Wainage

Antwort

4

warum können wir nicht laufen nur normal Asynchron-Code in einer .then() Kette, eine Rückkehr ein Promise.resolve() am Ende des Asynchron-Rückruf?

Sie können perfekt. Aber jeder Wert - sei es ein Versprechen oder was auch immer - ist return Ed von einem einfachen asynchronen Rückruf ist nur ignoriert wie üblich.

Es gibt nichts, das Starten der asynchronen Aktion innerhalb eines then Rückruf Änderungen darüber, setTimeout einfach nicht ein Versprechen zurückkehren - und das then wissen nicht über etwas asynchron geschieht, dass es warten konnte.

Wenn Sie ein Versprechen von einem Rückruf zurückkehren wollen und ein weiteres Versprechen für das schließliche Ergebnis zu erhalten, hat es ein then Rückruf sein:

asyncPromise() 
.then(function() { 
    return new Promise(function(resolve, reject) { 
// ^^^^^^ 
     setTimeout(resolve, 500); 
    }).then(function() { 
//  ^^^^^^^^^^^^^^^ 
     return Promise.resolve(); 
    }); 
}); 
0

Dann ist eine Sync-Funktion, so dass, wenn Sie innerhalb async Aufgabe dann tun mögen, können Sie ein Versprechen zurückkehren muss.

Auch Promise.all erwarten eine Reihe von Versprechen. Kein Array eines Arrays.

var asyncPromise = function() { 
    return new Promise(function(resolve, reject) { 
    setTimeout(function() { 
     console.log('Async Promise done'); 
     resolve(); 
    }, 1000); 
    }); 
}; 

var generateSignupPromises = function(qty) { 
    var promiseArray = []; 
    for (var i = 1; i <= qty; i++) { 
    promiseArray.push(
     function() { 
     return asyncPromise() 
     .then(function() { 
      console.log('Before Timeout'); 

      //Uncommenting this fixes the issue 
      return new Promise(function(resolve, reject) { 
      setTimeout(function() { 
      console.log('After Timeout'); 
      resolve(); 
      //return Promise.resolve(); 
      }, 500); 
      }) 
     }); 
     } 
    ); 
    } 
    return promiseArray; 
}; 

var test = generateSignupPromises(1); 

Promise.all([test[0]()]) 
.then(function() { 
    console.log('Done'); 
}); 

http://www.es6fiddle.net/imfe2sze/