Ich habe drei HTTP-Anrufe, die ich synchron tätigen muss, und wie übergebe ich Daten von einem Anruf zum anderen?
function first()
{
ajax()
}
function second()
{
ajax()
}
function third()
{
ajax()
}
function main()
{
first().then(second).then(third)
}
Ich habe versucht, die verzögerte Funktion für die beiden Funktionen zu verwenden, und eine Teillösung gefunden. Kann ich es auf drei Funktionen erweitern?
function first() {
var deferred = $.Deferred();
$.ajax({
"success": function (resp)
{
deferred.resolve(resp);
},
});
return deferred.promise();
}
function second(foo) {
$.ajax({
"success": function (resp)
{
},
"error": function (resp)
{
}
});
}
first().then(function(foo){second(foo)})
javascript
jquery
asynchronous
deferred
John Mcdock
quelle
quelle
sniker
jQuery.Promise (). Promise (). Promise (nichtig)Antworten:
Geben Sie in jedem Fall das von zurückgegebene jqXHR-Objekt zurück
$.ajax()
.Diese Objekte sind Promise-kompatibel und können daher mit
.then()
/.done()
/.fail()
/ verkettet werden.always()
..then()
ist die, die Sie in diesem Fall wollen, genau wie in der Frage.function first() { return $.ajax(...); } function second(data, textStatus, jqXHR) { return $.ajax(...); } function third(data, textStatus, jqXHR) { return $.ajax(...); } function main() { first().then(second).then(third); }
Argumente
data
,textStatus
undjqXHR
aus dem entstehen$.ajax()
in dem vorherigen Funktionsaufruf, dh.first()
Feedssecond()
undsecond()
Feedsthird()
.DEMO (mit
$.when('foo')
der Erfüllung eines erfüllten Versprechens anstelle von$.ajax(...)
).quelle
Es gibt tatsächlich einen viel einfacheren Ansatz, wenn Versprechen mit jQuery verwendet werden. Schauen Sie sich Folgendes an:
$.when( $.ajax("/first/call"), $.ajax("/second/call"), $.ajax("/third/call") ) .done(function(first_call, second_call, third_call){ //do something }) .fail(function(){ //handle errors });
Verketten Sie einfach alle Ihre Aufrufe mit dem Aufruf $ .when (...) und verarbeiten Sie die Rückgabewerte im Aufruf .done (...).
Hier ist eine exemplarische Vorgehensweise, wenn Sie es vorziehen: http://collaboradev.com/2014/01/27/understanding-javascript-promises-in-jquery/
quelle
Ziemlich spät zu antworten, aber ich denke, bei den Antworten fehlt ein direkter Code zum Verketten. Das Verketten von Ereignissen ist ziemlich einfach und verspricht Unterstützung bei der Abfrage. Ich benutze folgendes zum Verketten:
$.ajax() .then(function(){ return $.ajax() //second ajax call }) .then(function(){ return $.ajax() //third ajax call }) .done(function(resp){ //handle final response here })
Es ist einfach und nicht kompliziert für Schleifen oder mehrere verschachtelte Rückrufe.
quelle
Es ist viel einfacher als das.
$.ajax
gibt bereits ein Versprechen zurück (Zurückgestelltes Objekt), sodass Sie einfach schreiben könnenfunction first() { return $.ajax(...); }
quelle
first().then(second, third).then(fourth);
?.then()
(in 1.8+) zurück. Siehe api.jquery.com/deferred.thenSie können es funktionaler schreiben:
[function() { return ajax(...)}, function(data) { return ajax(...)}] .reduce(function(chain, callback) { if(chain) { return chain.then(function(data) { return callback(data); }); } else { return callback(); } }, null)
quelle
Der beste Weg, dies zu tun, besteht darin, eine wiederverwendbare Funktion dafür zu erstellen. Dies kann sogar mit nur einer Codezeile erfolgen, indem
reduce
:function chainPromises(list) { return list.reduce((chain, func) => chain ? chain.then(func) : func(), null); }
Diese Funktion akzeptiert eine Reihe von Rückrufen, die wie Ihre drei Funktionen ein Versprechungsobjekt zurückgeben.
Anwendungsbeispiel:
chainPromises([first, second, third]).then(function (result) { console.log('All done! ', result); });
Auf diese Weise ist das Ergebnis von
first
automatisch auch der Parameter vonsecond
. Im Grunde genommen geschieht also Folgendes:first().then(function(res1) { return second(res1) }) .then(function(res2) { return third(res2) }) .then(function(result) { console.log('All done! ', result) });
Und natürlich können Sie dem Array so viele Funktionen hinzufügen, wie Sie möchten.
quelle
Ich habe hier eine gut aussehende Lösung gefunden: Wie verkette ich eine Folge von verzögerten Funktionen in jQuery 1.8.x?
Und hier ist meine eigene Implementierung eines ähnlichen Ansatzes, etwas hässlich, aber wahrscheinlich funktionierend. Das Ergebnis jeder Methode wird als «Fortschrittsaktualisierung» für das zurückgegebene Versprechenobjekt gesendet.
$.chain = function() { var defer = $.Deferred(); var funcs = arguments; var left = funcs.length; function next(lastResult) { if(left == 0) { defer.resolve(); return; } var func = funcs[funcs.length - left]; // current func var prom = func(lastResult).promise(); // for promise will return itself, // for jquery ojbect will return promise. // these handlers will be launched in order we specify them prom.always(function() { left--; }).done(function(ret) { defer.notify({ idx: funcs.length-left, left: left, result: ret, success: true, }); }).fail(function(ret) { defer.notify({ idx: funcs.length-left, left: left, result: ret, success: false, }); }).always(function(ret) { next(ret); }); } next(); return defer.promise(); };
Wie kann ich es für Ihre Situation verwenden? Vielleicht nicht schön, aber es sollte funktionieren:
function first() { return ajax(...); } var id; funciton second() { return ajax(id, ...); } function third() { return ajax(id, ...); } $.chain(first, second, third).progress(function(p) { if(p.func == first) id = p.result.identifier; }).then(function() { alert('everything is done'); });
Oder Sie können diese ID-Variable einfach über die
first
Funktion zuweisen .Wenn Sie nur das Ergebnis der vorherigen Funktion benötigen, können Sie diesen Ansatz verwenden:
function first() { return ajax(...); } function second(first_ret) { return ajax(first_ret.id, ...); } function third(second_ret) { return ajax(second_ret.something, ...); }
quelle
notify()
Methode für einDeferred
Objekt aufrufen , übergeben Sie ihm ein Objekt. Dann alle , die Updates Fortschritte abonniert jenesDeferred
‚spromise
wird mit dem Objekt aufgerufen werden.Folgendes scheint zu funktionieren und ermöglicht es, dass die Liste der Funktionen dynamisch ist:
<html> <head> <title>demo chained synchronous calls</title> </head> <body> <script src="http://code.jquery.com/jquery-2.2.4.min.js"></script> <script type="text/javascript"> function one(parms) { console.log('func one ' + parms); return 1; } function two(parms) { console.log('func two ' + parms); return 2; } function three(parms) { console.log('func three ' + parms); return 3; } function four(parms) { console.log('func four ' + parms); return 4; } var funcs = ['one', 'two', 'three', 'four']; var rvals = [0]; function call_next_func() { if (funcs.length == 0) { console.log('done'); } else { var funcname = funcs.shift(); console.log(funcname); rvals.push(window[funcname](rvals)); call_next_func(); } } $(document).ready(function($){ call_next_func(); }); </script> </body> </html>
quelle
Um jquery Ajax-Anrufe zu verketten, habe ich Folgendes getan:
function A(){ return $.ajax({ url: url, type: type, data: data, datatype: datatype, success: function(data) { code here } }); } function B(){ return $.ajax({ url: url, type: type, data: data, datatype: datatype, success: function(data) { code here } }); } function C(){ return $.ajax({ url: url, type: type, data: data, datatype: datatype, success: function(data) { code here } }); } A().done(function(data){ B().done(function(data){ C(); }) });
quelle
Ich hatte gerade das gleiche Problem, Ajax-Anrufe zu verketten. Nachdem ich ein paar Tage lang versucht hatte, tat ich endlich
$.ajax({ async: false,...
das, was ich erreichen wollte. Daran habe ich einfach nicht gedacht. Es könnte anderen helfen ...quelle
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.