2017-12-07 20 views
0

Ich habe diesen Code jQuery-Code-Fragment:ein jQuery Versprechen, das immer gelingt?

$.get('/api/' + currentPage).done(function(data) { ... }) 
          .fail(...) 

Ich möchte $.get('/api/'+currentPage) mit dem Versprechen, ersetzen, die immer gelingt und gibt einen bestimmten Wert für data. Etwas wie:

let myData = { ... } // value of data I want to pass to the done function 

(new AlwaysSucceeds(myData)).done(function(data) { ... }) 
          .fail(...) 

Ich könnte ein Dummy-Objekt schustert, oder ich konnte die done Funktion extrahieren, aber ich möchte auf ein Minimum Änderungen an den Code zu halten.

Gibt es eine Möglichkeit, dies zu tun?

UPDATE: Um zu verdeutlichen, was los ist, ist der Code, mit dem ich arbeite, (here). Normalerweise wird diese App von einem Nodejs-Server bedient, der den /api/...-Aufruf implementiert, aber ich konvertiere es, um von einem statischen Seitenserver bedient zu werden. Ich weiß, was von der $.get Aufruf zurückgegeben wird. Damit Änderungen an den Code sauber ich einfach zu ändern mag, die an der Leitung:

let myData = {...} 

// $.get('/api/' + currentPage) -- comment out the $.get call 
(SOMETHINGHERE(myData)).done(function(data) { 

Der SOMETHINGHERE Ausdruck muss implementieren .done(f) , das die Funktion f mit myData anrufen und dann zurück einig Objekt, das .fail(...) implementiert die tut nichts.

+0

Was ist '.always()'? 'get()' ist eine Ajax-Methode, also ist es nicht unmöglich zu erwarten, dass es immer erfolgreich gemacht wird? Also .. wenn du das nicht kannst, dann könnte '' immer() 'eine Hilfe sein? – moon

+0

Ich denke, ich könnte diese Arbeit machen. Ich würde es vorziehen, die '$ .get()' überhaupt nicht auszuführen, obwohl ich die URL zu etwas harmlosem ändern könnte. – ErikR

+1

Sie können 'ersetzen $ .get()' mit allem, was ein Versprechen gibt, die Sie bereits mit den vorliegenden Daten ist haben. Es ist überhaupt nicht klar, welches Problem Sie eigentlich lösen wollen. Wenn Sie bereits die Daten haben, warum verwenden Sie überhaupt ein Versprechen? Das ist dann nur eine synchrone Operation. Keine Versprechen benötigt. Frage scheint mir unklar. – jfriend00

Antwort

3

Sie können mit einer Funktion ersetzen Sie einfach $.get(...), die ein Versprechen zurückgibt, die bereits mit den Daten, die Sie bereits haben gelöst ist.Und der kürzeste Weg, um ein bereits gelöst jQuery Versprechen zu bekommen, mit einem bestimmten Wert aufgelöst, ist dies:

$.when(myData).done(...) 

Je mehr Text-Buch, wie es in jQuery zu tun ist:

$.Deferred().resolve(myData).done(...) 

und, wenn Sie Ihre Logik auf die dem ES6 Standard wechseln (anstelle des nicht-Standard-jQuery Versprechen Verhaltens), dann könnten Sie verwenden:

Promise.resolve(myData).then(...).catch(...) 
+0

Leider hat jQuery Deferred einige Dinge, die native Versprechungen nicht haben, wenn man nicht-standardisierte Versprechungen der Bibliothek mit nativen Versprechungen kombiniert, ist es am besten anzunehmen, dass sie 'then' haben. OP verwendet 'done' und' fail', aber das sind keine Dinge, die ein natives Versprechen hat. – HMR

+1

@HMR - Da das OP hier die ganze Versprechenskette des Codes kontrolliert, zeige ich ihnen, wie sie einfach zu ES6 wechseln können, um das ganze Problem damit zu lösen. Jquery 3.x hat viel Kompatibilität mit ES6 verspricht, wenn Sie es verwenden und bleiben Sie mit '.then()'. Persönlich kodiere ich NIEMALS mit den jQuery-spezifischen '.done()' und '.fail()', weil es Sie wirklich verwirrt, wenn Sie ES6-Verhalten an anderer Stelle verwenden, da die beiden nicht auf die gleiche Weise funktionieren. Jedenfalls habe ich die ES6-Signatur der Vollständigkeit halber eingefügt und das OP kann wählen. Es gibt zwei weitere jQuery-Optionen, wenn das das OP möchte. – jfriend00

+0

Ich habe eine Antwort Warnung über Bibliotheken nicht Standardversprechen hinzugefügt. Nicht nur die Nicht-Standard-Methoden, die sie haben, sondern auch nicht das Standardverhalten. – HMR

1

Sie können dies erreichen, indem Sie die Konstruktorfunktion AlwaysSuceeds implementieren. Bitte sehen Sie sich das folgende Beispiel an.

function AlwaysSucceeds(data) { 
 
    this.data = data; 
 
} 
 

 
AlwaysSucceeds.prototype.done = function(fn) { 
 
    fn(this.data); 
 
    return this; 
 
} 
 

 
AlwaysSucceeds.prototype.fail = function(fn) { 
 
    return this; 
 
} 
 

 

 
var myData = { 
 
    a: 1 
 
}; 
 

 
(new AlwaysSucceeds(myData)).done(function(data) { 
 
    console.log(data) 
 
}).fail(function(data){ 
 

 
})

+0

Ja - das würde ich tun, wenn ich keine jQuery-Lösung finden könnte! – ErikR

1

Da jQuery Ajax-Funktionen nur $.Deferred Objekte zurückgeben, können Sie eine gerade ersetzen Deferred sofort aufgelöste:

$.Deferred().resolve(myData).then(...) 

In diesem speziellen Fall, wenn Sie es machen wollen einfach zwischen synchronen und asynchronen Code zu wechseln, und Sie haben Zugriff auf async/await, Sie können nur diese direkt verwenden:

try { 
    const data = await Promise.resolve($.get('/api/' + currentPage)); 
    // code in done 
} catch (err) { 
    // code in fail 
} 

würde

try { 
    const data = myData; 
    // code in done 
} catch (err) { 
    // code in fail (never runs unless other code throws exceptions) 
} 
1

Es ist nicht klar, was Sie wirklich wollen, aber sein carufull mit jQuery In Abgrenzung zu nativen Versprechungen hat das Deferred einige Standardmethoden, die native Versprechungen nicht haben.

Also um sicher zu sein, nehme ich immer an, es gibt eine thenable, etwas, das eine then hat, mit der man so ziemlich alles machen kann, was man will.

jQuery Latente verhalten sich nicht wie native Versprechen entweder (je nach Ausführung):

$.Deferred().reject("hello world") 
.then(
    undefined 
    ,x=>x 
) 
.then(
    x=>console.log("Never happens",x) 
) 

Promise.reject("hello world") 
.then(
    undefined 
    ,x=>x 
); 
.then(
    x=>console.log("Well behaved",x) 
); 

Promise.resolve().then(x=>{throw "nope"}) 
.then(undefined,err=>console.warn(err)); 

$.Deferred().resolve().then(x=>{throw "nope"})//crashes 
.then(undefined,err=>err); 

So wird es Retter sein nativer Versprechen zu verwenden und polyfill mit etwas, das wie native verhält.

die Frage nicht andernfalls Versprechen zu beantworten, wenn Sie eine Anfrage stellen möchten, aber eine Standard zurück, wenn es ablehnt und halten die gleiche einmal löst Rückkehr oder ablehnt Sie tun können:

const get = (p=>{ 
    (url) => { 
    p = p || 
    //return native promise or properly polyfilled one 
    Promise.resolve($.get(url)) 
    .then(
     undefined, 
     _=> {defaultobject:true} 
    ); 
    return p; 
    } 
})(); 

Ihre get-Funktion zurückkehren wird, keine fail ein native Versprechen so done und andere Dinge, die nicht Standard sind. „Versprechen“ aus verschiedenen Bibliotheken und nativen verspricht die Kombination wäre es am besten nur then verwenden, um

+0

Ich habe keine Ahnung, wie sich das auf die eigentliche Frage bezieht. In einer ES6-Welt wird die Interoperabilität am besten dadurch erreicht, dass man ein bekanntes ES6-Versprechen mit einem Versprechen abschließt, indem man es in 'Promise.resolve()' einpackt. Aber all das scheint für die Frage, die das OP gestellt hat, wirklich relevant zu sein, und wir brauchen keinen größeren Sidetrack zu machen, als Sie bereits hier haben. – jfriend00

+0

@ jfriend00 Ich weiß nicht, was die Frage ist. Möchte das OP etwas wie "Promise.resolve" oder eine Funktion, die ein nicht zurückweisbares '$ .get' hat, das nur einmal aufgerufen wird. Dann verwendet OP "jQuery.Defered" eine sichere Möglichkeit, sich selbst in den Fuß zu schießen, wenn Sie Ihre Versprechenskette mit nativen und anderen Bibliothekenversprechen kombinieren. – HMR

+0

Hmmm. Sie wissen nicht, was die Frage ist, aber Sie haben eine Antwort geschrieben? OK, ich schätze, ich höre auf damit zu kommentieren. – jfriend00

Verwandte Themen