如何按顺序执行javascript?
how to execute javascript deferred sequentially?
我想知道是否有一种方法可以按顺序和有条件地执行延迟任务。也就是说,我想按顺序执行一些异步任务,我只会根据前一个任务的结果执行下一个任务。承诺链的结果应该是最后执行的。
知道如何用 Jquery deferred 修补它。
编辑:
在我理解 ajax 正确调用之前,我为一个函数启动了以下代码,以验证一个值不在另一个值的相关值中。
function findBroaderOrNarrowerConceptInFieldSelectedList(field, value) {
var intputfields = $("#instance_" + field + "_wrapper" + " .ds-authority-value")
if (intputfields.length == 0)
return undefined;
//go over each input field and retreive the value
for (var i = 0; i < intputfields.length; i++) {
//check if our value is in the broader concepts of the input field concept
//if true return the wrapper element, if false next steps
if (is_broader_concept(value.id, $(intputfields[i]).attr('value'))) {
var WrapperdivId = "#" + $(intputfields[i]).attr('name').replace("_authority", "") + "_wrapper";
return $($(WrapperdivId)[0]);
}
//check if our value is in the narrower concepts of the input field concept
//if true return the wrapper element
if (is_narrower_concept(value.id, $(intputfields[i]).attr('value'))) {
var WrapperdivId = "#" + $(intputfields[i]).attr('name').replace("_authority", "") + "_wrapper";
return $($(WrapperdivId)[0]);
}
}
return undefined
}
问题是我的 is_broader_concept 看起来像这样:
function is_broader_concept(broaderuri, concepturi) {
return getBroaderConcepts(concepturi).then(function(data, textStatus, jqXHR ) {
var broaders = data
if (broaders.length == 0)
return false;
for (var i = 0; i < broaders.length; i++) {
if (broaders[i].uri == broaderuri)
return true;
}
});
}
现在我已经了解了 deferred 和 promise(不是很新,因为我是在 scala(promise 和 future)中做的),我想调整我的第一个方法来处理 deferred。然而,我没有看到任何结构可以帮助我轻松实现我想要的。
编辑 2:
我发现了以下库,如果您不介意启动许多并行任务,它非常有用。事实上它可以 return 在第一个成功的时候。它是对 When 的修改。尽管我认为不必全部调用它们会很好
https://github.com/terrycojones/jquery-when2
编辑 3:
我更想寻找一个完全没有错误的库,可以像 https://codereview.stackexchange.com/questions/38420/sequential-function-call-in-javascript or Conditionals on a chained deferred in jquery
EDIT4: Update based on the response by @Roamer-1888
正确的 is_broader 并且更窄,适用于他的解决方案
function is_broader_concept_Promise(broaderuri, field) {
var uri = field.value.substr(field.value.indexOf("http://"));
return getBroaderConcepts(uri).then(function(data, textStatus, jqXHR ) {
var broaders = data;
if (broaders.length == 0)
return $.Deferred( function( d){ d.reject(); }).promise();
for (var i = 0; i < broaders.length; i++) {
if (broaders[i].uri == broaderuri)
return field;
}
return $.Deferred( function( d){ d.reject(); }).promise();
});
}
function is_narrower_concept_Promise(narroweruri, field) {
var uri = field.value.substr(field.value.indexOf("http://"));
return getNarrowerConcepts(uri).then(function(data, textStatus, jqXHR ) {
var narrowers = data;
if (narrowers.length == 0)
return $.Deferred( function( d){ d.reject(); }).promise();
for (var i = 0; i < narrowers.length; i++) {
if (narrowers[i].uri == narroweruri)
return field;
}
return $.Deferred( function( d){ d.reject(); }).promise();
});
}
非常感谢,
米
PS:我大约一个月前开始jQuery。
.done()
处理程序只会在任务成功时触发,因此您可以像这样使用嵌套的 done()
处理程序:
step1().done(function() {
step2().done(function() {
step3().done(function() {
// etc.
});
});
});
(其中 step1()
、step2()
和 step3()
return 延迟对象)
如果您正在制作自己的延迟对象,您可以调用 deferred.resolve()
表示任务成功,或调用 deferred.reject()
表示任务失败。
有关详细信息,请参阅 jQuery.Deferred()
文档。
When-JS 恰到好处。这就是我要找的
通俗地说,objective 可以概括如下:
"At each turn of a loop, if neither a broader-concept NOR a narrower-concept is discovered (asynchronously), then continue to test, otherwise break out of the loop".
在同步代码中这是微不足道的,但在异步世界中有一些障碍需要跳过。特别是,jQuery 不为异步 NOR
提供语法糖。但是,我们可以以自定义 jQuery.when_none()
方法的形式编写一个:
jQuery.when_none = function() {
//if all input-promises reject, then fulfil.
//if any input-promise fulfills, then reject.
var promises = $.map(arguments, function(p) {
return $.Deferred(function(dfrd) {
p.then(dfrd.reject, dfrd.resolve);//resolve/reject inversion
}).promise();
});
return $.when.apply(null, promises);
};
接下来,将 is_broader_concept()
(和 is_narrower_concept()
)修改为 return 一个将是 resolved/rejected 的承诺,而不是将用布尔值 [=41] 解析的承诺=](还有其他小改动):
function is_broader_concept(uri, fld) {
return getBroaderConcepts(fld.value).then(function(data) {
if(data.indexOf(uri) > -1) {
return fld; // The success state will be inverted by $.when_none(), and the rest of the .then() chain will be bypassed
} else {
return $.Deferred().reject().promise(); // The fail state will be inverted by $.when_none(), permitting the next step of the .then() chain.
}
});
}
最后,在 findBroaderOrNarrowerConceptInFieldSelectedList()
中:
- 通过利用
.reduce()
遍历“.ds-authority-value”字段来构建 .then()
链。
- 使用自定义方法
$.when_none()
实现所需的 NOR 逻辑以控制承诺链。
function findBroaderOrNarrowerConceptInFieldSelectedList(field, value) {
return $("#instance_" + field + "_wrapper").find(".ds-authority-value").get().reduce(function(promise, fld) {
return promise.then(function() {
return $.when_none(
is_broader_concept(value.id, fld),
is_narrower_concept(value.id, fld)
);
});
}, $.when()).then(function() {
/* success: ie "not found", so reinvert the logic to force down the fail path */
return $.Deferred().reject(value.id + ' is neither broader-concept nor narrower-concept.');
}, function(fld) {
/* fail: ie "found", so reinvert the logic to force down the success path */
return $.when($('#' + fld.name.replace('_authority', '') + '_wrapper')); // $(fld) ???
});
}
可能有更简单的方法来实现 NOR 逻辑,但我现在想不出来。
我想知道是否有一种方法可以按顺序和有条件地执行延迟任务。也就是说,我想按顺序执行一些异步任务,我只会根据前一个任务的结果执行下一个任务。承诺链的结果应该是最后执行的。
知道如何用 Jquery deferred 修补它。
编辑:
在我理解 ajax 正确调用之前,我为一个函数启动了以下代码,以验证一个值不在另一个值的相关值中。
function findBroaderOrNarrowerConceptInFieldSelectedList(field, value) {
var intputfields = $("#instance_" + field + "_wrapper" + " .ds-authority-value")
if (intputfields.length == 0)
return undefined;
//go over each input field and retreive the value
for (var i = 0; i < intputfields.length; i++) {
//check if our value is in the broader concepts of the input field concept
//if true return the wrapper element, if false next steps
if (is_broader_concept(value.id, $(intputfields[i]).attr('value'))) {
var WrapperdivId = "#" + $(intputfields[i]).attr('name').replace("_authority", "") + "_wrapper";
return $($(WrapperdivId)[0]);
}
//check if our value is in the narrower concepts of the input field concept
//if true return the wrapper element
if (is_narrower_concept(value.id, $(intputfields[i]).attr('value'))) {
var WrapperdivId = "#" + $(intputfields[i]).attr('name').replace("_authority", "") + "_wrapper";
return $($(WrapperdivId)[0]);
}
}
return undefined
}
问题是我的 is_broader_concept 看起来像这样:
function is_broader_concept(broaderuri, concepturi) {
return getBroaderConcepts(concepturi).then(function(data, textStatus, jqXHR ) {
var broaders = data
if (broaders.length == 0)
return false;
for (var i = 0; i < broaders.length; i++) {
if (broaders[i].uri == broaderuri)
return true;
}
});
}
现在我已经了解了 deferred 和 promise(不是很新,因为我是在 scala(promise 和 future)中做的),我想调整我的第一个方法来处理 deferred。然而,我没有看到任何结构可以帮助我轻松实现我想要的。
编辑 2:
我发现了以下库,如果您不介意启动许多并行任务,它非常有用。事实上它可以 return 在第一个成功的时候。它是对 When 的修改。尽管我认为不必全部调用它们会很好
https://github.com/terrycojones/jquery-when2
编辑 3:
我更想寻找一个完全没有错误的库,可以像 https://codereview.stackexchange.com/questions/38420/sequential-function-call-in-javascript or Conditionals on a chained deferred in jquery
EDIT4: Update based on the response by @Roamer-1888
正确的 is_broader 并且更窄,适用于他的解决方案
function is_broader_concept_Promise(broaderuri, field) {
var uri = field.value.substr(field.value.indexOf("http://"));
return getBroaderConcepts(uri).then(function(data, textStatus, jqXHR ) {
var broaders = data;
if (broaders.length == 0)
return $.Deferred( function( d){ d.reject(); }).promise();
for (var i = 0; i < broaders.length; i++) {
if (broaders[i].uri == broaderuri)
return field;
}
return $.Deferred( function( d){ d.reject(); }).promise();
});
}
function is_narrower_concept_Promise(narroweruri, field) {
var uri = field.value.substr(field.value.indexOf("http://"));
return getNarrowerConcepts(uri).then(function(data, textStatus, jqXHR ) {
var narrowers = data;
if (narrowers.length == 0)
return $.Deferred( function( d){ d.reject(); }).promise();
for (var i = 0; i < narrowers.length; i++) {
if (narrowers[i].uri == narroweruri)
return field;
}
return $.Deferred( function( d){ d.reject(); }).promise();
});
}
非常感谢,
米
PS:我大约一个月前开始jQuery。
.done()
处理程序只会在任务成功时触发,因此您可以像这样使用嵌套的 done()
处理程序:
step1().done(function() {
step2().done(function() {
step3().done(function() {
// etc.
});
});
});
(其中 step1()
、step2()
和 step3()
return 延迟对象)
如果您正在制作自己的延迟对象,您可以调用 deferred.resolve()
表示任务成功,或调用 deferred.reject()
表示任务失败。
有关详细信息,请参阅 jQuery.Deferred()
文档。
When-JS 恰到好处。这就是我要找的
通俗地说,objective 可以概括如下:
"At each turn of a loop, if neither a broader-concept NOR a narrower-concept is discovered (asynchronously), then continue to test, otherwise break out of the loop".
在同步代码中这是微不足道的,但在异步世界中有一些障碍需要跳过。特别是,jQuery 不为异步 NOR
提供语法糖。但是,我们可以以自定义 jQuery.when_none()
方法的形式编写一个:
jQuery.when_none = function() {
//if all input-promises reject, then fulfil.
//if any input-promise fulfills, then reject.
var promises = $.map(arguments, function(p) {
return $.Deferred(function(dfrd) {
p.then(dfrd.reject, dfrd.resolve);//resolve/reject inversion
}).promise();
});
return $.when.apply(null, promises);
};
接下来,将 is_broader_concept()
(和 is_narrower_concept()
)修改为 return 一个将是 resolved/rejected 的承诺,而不是将用布尔值 [=41] 解析的承诺=](还有其他小改动):
function is_broader_concept(uri, fld) {
return getBroaderConcepts(fld.value).then(function(data) {
if(data.indexOf(uri) > -1) {
return fld; // The success state will be inverted by $.when_none(), and the rest of the .then() chain will be bypassed
} else {
return $.Deferred().reject().promise(); // The fail state will be inverted by $.when_none(), permitting the next step of the .then() chain.
}
});
}
最后,在 findBroaderOrNarrowerConceptInFieldSelectedList()
中:
- 通过利用
.reduce()
遍历“.ds-authority-value”字段来构建.then()
链。 - 使用自定义方法
$.when_none()
实现所需的 NOR 逻辑以控制承诺链。
function findBroaderOrNarrowerConceptInFieldSelectedList(field, value) {
return $("#instance_" + field + "_wrapper").find(".ds-authority-value").get().reduce(function(promise, fld) {
return promise.then(function() {
return $.when_none(
is_broader_concept(value.id, fld),
is_narrower_concept(value.id, fld)
);
});
}, $.when()).then(function() {
/* success: ie "not found", so reinvert the logic to force down the fail path */
return $.Deferred().reject(value.id + ' is neither broader-concept nor narrower-concept.');
}, function(fld) {
/* fail: ie "found", so reinvert the logic to force down the success path */
return $.when($('#' + fld.name.replace('_authority', '') + '_wrapper')); // $(fld) ???
});
}
可能有更简单的方法来实现 NOR 逻辑,但我现在想不出来。