Synchrone Versprechen Auflösung (bluebird vs. jQuery)

Entwickelt ich eine kleine lib für die Dynamics CRM REST/ODATA webservice (CrmRestKit). Die lib dependes auf jQuery und nutzt das Versprechen-Muster, repectivly das Versprechen-wie-Muster von jQuery.

Jetzt möchte ich port diese lib zu bluebird und entfernen Sie den jQuery-Abhängigkeit. Aber ich stehe vor einem problem, weil bluebird nicht unterstützen die synchrone Auflösung des promise-Objekte.

Einige Kontextinformationen:

Die API der CrmRestKit nimmt einen optionalen parameter, der definiert, ob der web-service-Aufruf durchgeführt werden sollten, sync oder async-Modus:

CrmRestKit.Create( 'Account', { Name: "foobar" }, false ).then( function ( data ) {
   ....
} );

Geben Sie "true" oder lassen Sie den letzten parameter, wird die Methode erstellt den Datensatz zu synchronisieren. - Modus.

Manchmal ist es notwendig, führen einen Betrieb im sync-Modus, zum Beispiel schreiben Sie JavaScript-code für Dynamics CRM, involed für das speichern-Ereignis einer form und in dieser event-handler, den Sie brauchen, um sync-operation für die Validierung (z.B. überprüfen, dass eine bestimmte Anzahl von Kind-Datensätze vorhanden sind, bei der richtigen Anzahl von Datensätzen vorhanden sein, brechen Sie die speichern-operation, und eine Fehlermeldung anzeigen).

Mein problem ist jetzt das folgende: bluebird unterstützt nicht die Auflösung im sync-Modus. Zum Beispiel wenn ich den folgenden, der "dann" - handler aufgerufen, der in async Mode:

function print( text ){

    console.log( 'print -> %s', text );

    return text;
}

///
///'Promise.cast' cast the given value to a trusted promise. 
///
function getSomeTextSimpleCast( opt_text ){

    var text = opt_text || 'Some fancy text-value';

    return Promise.cast( text );
}

getSomeTextSimpleCast('first').then(print);
print('second');

Die Ausgabe ist folgende:

print -> second
print -> first

Ich würde erwarten, dass die "zweite" wird nach der "ersten", weil die Versprechen ist bereits gelöst mit einem Wert. Also ich würde davon ausgehen, dass eine dann-Ereignis-handler wird sofort aufgerufen , wenn angewandt, auf eine bereits beschlossene promise-Objekt.

Wenn ich das gleiche tun (verwenden Sie dann schon gelöst Versprechen) mit jQuery habe ich mein erwartetes Ergebnis:

function jQueryResolved( opt_text ){

    var text = opt_text || 'jQuery-Test Value',
    dfd =  new $.Deferred();

    dfd.resolve(text);

        //return an already resolved promise
    return dfd.promise();
}

jQueryResolved('third').then(print);
print('fourth');

Diese erzeugt die folgende Ausgabe:

print -> third
print -> fourth

Ist es eine Möglichkeit zu bluebird arbeiten in der gleichen Weise?

Update:
Der code war nur das problem veranschaulichen. Die Idee der lib ist: Unabhängig von der Ausführung-Modus (sync, async) der Anrufer wird es immer um ein promise-Objekt.

Hinsichtlich "... der Benutzer gefragt wird,... scheint nicht zu keinen Sinn": Wenn Sie zwei Methoden "CreateAsync" und "CreateSync" außerdem ist es bis zu dem Benutzer, zu entscheiden, wie die operation ausgeführt wird.

Sowieso mit der aktuellen Implementierung der default-Verhalten (der Letzte parameter ist optional), ist eine asynchrone Ausführung. Also 99% des Codes erfordert ein promise-Objekt, der optionale parameter ist nur für die 1% Fälle, in denen müssen Sie einfach einen sync-Ausführung. Desweiteren habe ich entwickelt, um die lib für mich und ich in 99,9999% der Fall der async-Modus, aber ich dachte, es ist schön, die option zu gehen die sync-Straße, wie Sie möchten.

Aber ich denkt, ich habe die Stelle ein sync-Methode sollte einfach wieder den Wert. Für die nächste Version (3.0) werde ich umsetzen "CreateSync" und "CreateAsync".

Vielen Dank für deinen input.

Update-2
Meine intension für den optionalen parameter war zu gewährleisten, besteht das Verhalten UND verhindern, dass Logik-Fehler. Davon aus, dass Ihr als Verbraucher meiner methode "GetCurrentUserRoles" verwendet lib. Also die Methode immer zurück ein Versprechen, das bedeutet, dass Sie verwenden müssen, wird der "then" - Methode, um code auszuführen, hängt vom Ergebnis. Also, wenn einige Schreibvorgänge code wie diesem, der ich Zustimmen, dass es Total falsch ist:

var currentUserRoels = null;

GetCurrentUserRoles().then(function(roles){

    currentUserRoels = roles;
});

if( currentUserRoels.indexOf('foobar') === -1 ){

    //...
}

Ich bin damit einverstanden, dass dieser code wird unterbrochen, wenn die Methode "GetCurrentUserRoles" änderungen aus dem sync async.

Aber ich verstehe, dass das ich nicht ein gutes design, weil die Verbraucher sollten jetzt, dass er sich mit einer async-Methode.

Warum auf der Erde würden Sie wieder ein Versprechen, wenn der Aufruf ist synchron? Einfach nur wieder den Wert der Regel.
Ich möchte darauf hinweisen, dass der obige Kommentar ist von der Autorin von Bluebird.
Nein, es ist eine überladene Funktion (2 verschiedene Funktionen), bei denen der Anrufer wählt synchronity. Die API könnte genauso gut CrmRestKit.CreateAsync und CrmRestKit.CreateSync statt CrmRestKit.Create({async: ?}). Dies ist völlig Verschieden von einer Funktion, die vielleicht manchmal wissen, seine Rückkehr Wert synchron (z.B. 1st level cache-Datenbank-Aufruf)
absolut nicht, sync-Funktionen muss wieder direkte Werte. Schlechteste API-immer wenn Sie verspricht mit synchronen Funktionen. Was jQuery macht, ist sehr falsch, denn es führt zu unvorhersehbaren Reihenfolge der Ausführung, wenn eine Funktion wirklich synchrone und asychrone - das ist, wenn der Anrufer nicht zu entscheiden. Auch ist es nicht "andere API" überhaupt Rückgabe von Werten aus einer synchronen Funktionen und verspricht von asynchronen. Suchen Sie im Knoten fs-API oder XMLHttpRequest-beispielsweise - weder Kräfte Sie Rückrufe oder verspricht, wenn Sie synchrone Aufrufe.
OP, ich denke, Sie haben genug Informationen, um entweder zu akzeptieren, die Antworten oder Rollen Sie Ihre eigenen, nicht wahr ?

InformationsquelleAutor thuld | 2014-01-15

Schreibe einen Kommentar