2017-03-16 4 views
1

Hier ist meine Situation:Async Funktion innerhalb Promises

fetchData(foo).then(result => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(result + bar); 
     }, 0) 
    }); 
}).then(result => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(result + woo); 
     }, 0) 
    }); 
}).then(result => { 
    setTimeout(() => { 
     doSomething(result); 
    }, 0) 
}); 

Wo jeder SetTimeout ist ein anderer Asynchron-Betrieb des Callback-Muster.

Es ist wirklich schmerzhaft jede Funktion in einem Versprechen zu wickeln, ich fühle mich wie der Code soll wie folgt aussehen:

fetchData(foo).then(result => { 
    setTimeout(() => { 
     return result + bar; 
    }, 0) 
}).then(result => { 
    setTimeout(() => { 
     return result + woo; 
    }, 0) 
}).then(result => { 
    setTimeout(() => { 
     doSomething(result); 
    }, 0) 
}); 

Offensichtlich ist dies nicht funktioniert.

Nutze ich Promises richtig? Muss ich wirklich alle vorhandenen asynchronen Funktionen in Versprechen einbinden?

EDIT:

Eigentlich merke ich mein Beispiel für meine Situation nicht völlig reprensentative war, habe ich nicht machen deutlich, dass die setTimeout in meinem Beispiel zu verstehen ist en async Betrieb reprensent. Diese Situation ist repräsentativer für meine Situation:

fetchData(foo).then(result => { 
    return new Promise((resolve, reject) => { 
     asyncOperation(result, operationResult => { 
      resolve(operationResult); 
     }, 0) 
    }); 
}).then(result => { 
    return new Promise((resolve, reject) => { 
     otherAsyncOperation(result, otherAsyncResult => { 
      resolve(otherAsyncResult); 
     }, 0) 
    }); 
}).then(result => { 
     doSomething(result); 
}); 
+0

Sie können benutzerdefiniertes Ereignis verwenden, wenn Sie nicht versprechen wollen. Dieses Ereignis wird bei jeder Erkennungsänderung ausgelöst! (https://www.sitepoint.com/javascript-custom-events/) .... Aber warum Sie nicht gerne Versprechen verwenden? –

+1

Es gibt Module wie ['pify'] (https://github.com/sindresorhus/pify), mit denen Sie vorhandene Callback-basierte Async-Funktionen promotifizieren können. Außerdem bietet eine angemessene Anzahl von Paketen _both_ Versprechen und Callback-Unterstützung für ihre asynchronen Funktionen (wenn Sie keine Callback-Funktion übergeben, geben sie eine Zusage zurück). Aber ich kann nicht sagen, ob das auf Ihre Situation zutrifft. – robertklep

+0

^^ yeah oder 'bluebird' ist sehr einfach und verhält sich genau wie native Promises, aber freundlicher für Callbacks im Node-Stil. [link] (http://bluebirdjs.com/docs/api/promise.fromcallback.html) – user3821538

Antwort

3

Said so, wenn Sie das Geräusch zu erzeugen, das Versprechen reduzieren wollen setTimeout jedes Mal zu wickeln, können Sie eine Nutzenfunktion setTimeoutWithPromise erstellen

Nutze ich Promises richtig? Muss ich wirklich alle vorhandenen asynchronen Funktionen in Versprechen einbinden?

Ja. Ja.

Ich fühle mich wie der Code wie dieser No

aussehen sollte, sollte es nicht. Es sollte eher so aussehen:

function promiseOperation(result) { 
    return new Promise((resolve, reject) => { 
     asyncOperation(result, resolve, 0) 
    }); 
} 
function otherPromiseOperation(result) { 
    return new Promise((resolve, reject) => { 
     otherAsyncOperation(result, resolve, 0) 
    }); 
} 

fetchData(foo).then(promiseOperation).then(otherPromiseOperation).then(doSomething); 

es jede Funktion in einem Versprechen wirklich schmerzhaft ist

Nun zu wickeln, nicht immer wieder schreiben sie jedes Mal aus. Sie können dieses Wrapping in eine Funktion abstrahieren!

function promisify(fn) { 
    return value => new Promise(resolve => { 
     fn(value, resolve, 0) 
    }); 
} 
const promiseOperation = promisify(asyncOperation); 
const otherPromiseOperation = promisify(otherAsyncOperation); 
fetchData(foo).then(promiseOperation).then(otherPromiseOperation).then(doSomething); 

Beachten Sie, dass die meisten versprechen Bibliotheken werden mit einer solchen eine promisification Funktion enthalten, so dass Ihre gesamte Code auf diese drei Linien reduziert.

0

Du Versprechen rechte Seite. Nur eine kleine Notiz auf dem ersten Code-Snippet: Sie sind nicht ein Versprechen aus dem letzten then() Rückruf Rückkehr:

... 
}).then(result => { 
    setTimeout(() => { 
     doSomething(result); 
    }, 0) 
}); 

Das ist richtig, wenn Sie müssen einfach nur einen asynchronen Betrieb zu tun, ohne die an den Aufrufer von fetchData Rückkehr Wert der letzten asynchronen Operation. Wenn Sie diesen Wert zurückgeben müssen, müssen Sie konvertieren diese Operation zu versprechen, zu:

fetchData(foo).then(result => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(result + bar); 
     }, 0) 
    }); 
}).then(result => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(result + woo); 
     }, 0) 
    }); 
}).then(result => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(doSomething(result)); 
     }, 0) 
    }); 
}); 

Hier nehme ich doSomething ist eine sync Funktion einen Wert zurückkehrt.

function setTimeoutWithPromise(operation, millisec) { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(operation()); 
     }, millisec) 
    }); 
} 

und säubern Sie Ihren Code:

fetchData(foo) 
    .then(result => setTimeoutWithPromise(() => result + bar, 0)) 
    .then(result => setTimeoutWithPromise(() => result + woo, 0)) 
    .then(result => setTimeoutWithPromise(() => doSomething(result), 0)); 
Verwandte Themen