如何避免硬codeD,在Javascript / jQuery的链式异步函数? [英] How to avoid hard-coded, chained asynchronous functions in Javascript/jQuery?
问题描述
几乎所有在我的程序中的功能有某种异步调用,但它们都依赖于一些previous作用的结果。这一点,因为,我已经硬codeD的下一个函数调用到每一个人一个作为这样的:
Almost all of the functions in my program have some sort of asynchronous call, but they all rely on some previous function's results. Because of that, I've hard-coded the next function call into each individual one as such:
function getStuff() {
$.ajax({
...
success: function(results) {
// other functions involving results
getMoreStuff(results);
}
});
}
function getMoreStuff(results) {
$.ajax({
...
success: function(moreResults) {
// other functions involving moreResults
doSomethingWithStuff(moreResults);
}
);
}
等。这是一家大型连锁其中每个函数调用下。虽然这个工作计划中,它使每个单独的功能形同虚设。
And so on. It's a large chain where each function calls the next. While this works within the program, it makes each function useless individually.
我有点失去了关于如何避免这个问题。我无法弄清楚如何使用一般的回调函数,因为当我做的函数调用,它结束了像这样(使用上述功能):
I'm a bit lost on how to avoid this problem. I couldn't figure out how to use general callback functions, because when I make the function calls, it ends up like this (using the functions above):
getStuff(function() {
getMoreStuff(results, doSomethingWithStuff);
};
不过,结果还没有被定义。
But then 'results' hasn't been defined yet.
该解决方案似乎是显而易见的,我只是作为一个有点密集了。对不起!
The solution seems obvious, I'm just being a bit dense about it. Sorry!
推荐答案
您有几个选择。你可以有你的code。使用这些功能看起来像这样,通过回调:
Overview
You have a couple of choices. You can have your code using those functions look like this, using callbacks:
getStuff(function(results) {
getMoreStuff(results, doSomethingWithStuff);
});
或类似这样的,使用jQuery的延迟
和无极
目标:
getStuff().then(getMoreStuff).then(doSomethingWithStuff):
使用回调
同时拥有 getStuff
和 getMoreStuff
接受一个参数是一个回调,当他们完成调用,如
Using callbacks
Have both getStuff
and getMoreStuff
accept an argument that is a callback to call when they're done, e.g.:
function getStuff(callback) {
// ^------------------------------ callback argument
$.ajax({
...
success: function(results) {
// other functions involving results
callback(results);
// ^------------------------------------ use the callback arg
}
});
}
......,同样为 getMoreStuff
。
jQuery的 AJAX
功能集成了延迟
和无极
功能。你可以再补充返回
将现有的功能,使这项工作,例如:
jQuery's ajax
function integrates with its Deferred
and Promise
features. You can just add return
to your existing functions to make that work, e.g.:
function getStuff(callback) {
return $.ajax({
...
});
}
(注意:没有必要在成功
回调)的
(Note: No need for the success
callback.)
那么这code:
getStuff().then(getMoreStuff).then(doSomethingWithStuff);
做到这一点:
does this:
-
getStuff
开始其AJAX
呼叫并返回无极
的调用创建。
getStuff
starts itsajax
call and returns thePromise
that call creates.
在该 AJAX
调用完成和解决的承诺, getMoreStuff
被调用的结果 AJAX
通话作为第一个参数。它开始的及其的 AJAX
电话。
When that ajax
call completes and resolves the promise, getMoreStuff
is called with the results of the ajax
call as its first argument. It starts its ajax
call.
在 getMoreStuff
的 AJAX
调用完成, doSomethingWithStuff
被调用的结果的是的调用(一个在 getMoreStuff
)。
When getMoreStuff
's ajax
call completes, doSomethingWithStuff
is called with the results of that call (the one in getMoreStuff
).
要使用重要的是然后
,不是完成
,以获得在每个阶段传递正确的结果。 (如果你使用完成
,无论 getMoreStuff
和 doSomethingWithStuff
将看到 getStuff
的 AJAX
电话。)
It's important to use then
, not done
, in order to get the correct results passed on at each stage. (If you use done
, both getMoreStuff
and doSomethingWithStuff
will see the results of getStuff
's ajax
call.)
下面是一个使用一个完整的示例 AJAX
:
Here's a full example using ajax
:
小提琴 | 备用摆弄 AJAX
通话服用,每次一秒钟(使得它更容易看看发生了什么)
Fiddle | Alternate Fiddle with the ajax
calls taking one second each (makes it easier to see what's happening)
function getStuff() {
display("getStuff starting ajax")
return $.ajax({
url: "/echo/json/",
type: "POST",
data: {json: '{"message": "data from first request"}'},
dataType: "json"
});
}
function getMoreStuff(results) {
display("getMoreStuff got " + results.message + ", starting ajax");
return $.ajax({
url: "/echo/json/",
type: "POST",
data: {json: '{"message": "data from second request"}'},
dataType: "json"
});
}
function doSomethingWithStuff(results) {
display("doSomethingWithStuff got " + results.message);
}
getStuff().then(getMoreStuff).then(doSomethingWithStuff);
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
输出:
getStuff starting ajax
getMoreStuff got data from first request, starting ajax
doSomethingWithStuff got data from second request
您不需要使用 AJAX
来获得这样的好处,你可以用你自己的延迟
和无极
的对象,它可以让你写这样的链条:
You don't need to be using ajax
to get the benefit of this, you can use your own Deferred
and Promise
objects, which lets you write chains like this:
one().then(two).then(three);
......任何情况下,你可能有异步的完成。
...for any situation where you may have asynchronous completions.
下面是一个非 - AJAX
例如:
Here's a non-ajax
example:
function one() {
var d = new $.Deferred();
display("one running");
setTimeout(function() {
display("one resolving");
d.resolve("one");
}, 1000);
return d.promise();
}
function two(arg) {
var d = new $.Deferred();
display("Two: Got '" + arg + "'");
setTimeout(function() {
display("two resolving");
d.resolve("two");
}, 500);
return d.promise();
}
function three(arg) {
var d = new $.Deferred();
display("Three: Got '" + arg + "'");
setTimeout(function() {
display("three resolving");
d.resolve("three");
}, 500);
return d.promise();
}
one().then(two).then(three);
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
输出:
one running
one resolving
Two: Got 'one'
two resolving
Three: Got 'two'
three resolving
这两个(即 AJAX
例如,非 - AJAX
为例)可以结合在必要时。举例来说,如果我们把 getStuff
从 AJAX
的例子,我们决定我们之前做数据的一些处理我们把这项工作交给 getMoreStuff
,我们会改变这样的:小提琴一>
These two (the ajax
example and the non-ajax
example) can be combined when necessary. For instance, if we take getStuff
from the ajax
example and we decide we have to do some processing on the data before we hand it off to getMoreStuff
, we'd change it like this: Fiddle
function getStuff() {
// Create our own Deferred
var d = new $.Deferred();
display("getStuff starting ajax")
$.ajax({
url: "/echo/json/",
type: "POST",
data: {json: '{"message": "data from first request"}', delay: 1},
dataType: "json",
success: function(data) {
// Modify the data
data.message = "MODIFIED " + data.message;
// Resolve with the modified data
d.resolve(data);
}
});
return d;
}
请注意,我们如何使用这些并没有改变:
Note that how we use that didn't change:
getStuff().then(getMoreStuff).then(doSomethingWithStuff);
所有这些改变是在 getStuff
。
这是对整个承诺概念的伟大的事情之一(这是不是在所有具体到jQuery的,但jQuery的为我们提供了方便的版本使用),它是梦幻般的去耦的事情。
This is one of the great things about the whole "promise" concept (which isn't at all specific to jQuery, but jQuery gives us handy versions to use), it's fantastic for decoupling things.
这篇关于如何避免硬codeD,在Javascript / jQuery的链式异步函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!