问题:
我一直在摸索,试图弄清楚为什么我使用$ .when.apply()。then()编写了一些代码来解析多个promise,然后返回数据似乎不同步,返回了未解决的承诺,然后在调用回调后解决承诺。
这是我一直在使用的模拟代码:
format(function(r) {
console.log('Done!', r);
});
function format(callback) {
var promises = [];
var items = [
{model: 'George'}
];
$.each(items, function (i, item) {
var selectedSeries = item.model;
promises.push(getSeriesDescription(selectedSeries));
});
$.when.apply($, promises).then(function (seriesInfo) {
console.log('Calling back');
callback(seriesInfo);
});
}
function getSeriesDescription(series) {
return new Promise(function (resolve, reject) {
getSeriesNotes().then(function (notes) {
console.log('Processing Notes...');
var rNotes;
$.each(notes.data, function () {
if (series !== 'undefined') {
console.log('Checking series ' + this.first_name + ' against ' + series + '...');
if (this.first_name == series) {
console.log('Series found!');
rNotes = this;
return false;
}
}
});
if (rNotes !== undefined) {
console.log('Returning series specific notes...');
resolve(rNotes);
} else {
resolve(notes);
}
});
});
}
function getSeriesNotes() {
return $.ajax({
url: 'https://reqres.in/api/users?delay=2',
dataType: 'json',
type: 'GET',
data: '',
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
我发现了什么:
经过无数次调试,我终于意识到意外的行为似乎是我使用的jQuery版本的结果。下面,我有两个小提琴,它们的代码完全相同,但版本不同。 (我发布了jsfiddles,因为StackOverflow的没有jQuery 3.x版本)
jQuery 2.1.3:
https://jsfiddle.net/persononfire/1epgnfuh/2/
jQuery 3.1.1:
https://jsfiddle.net/persononfire/a9gc0y14/
通过查看控制台,您将看到v3版本返回的每个版本,而v2版本却没有。
预期结果:
加工说明...
(索引):58检查乔治对阵乔治...
(索引):找到60个系列!
(索引):67返回系列特定说明...
(索引):46回电
(索引):31完成! {id:1,first_name:“ George”,last_name:“ Bluth”,头像:“ https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg”}
版本2.1.3首先返回最后两行,然后按我期望的顺序返回其他所有内容。
问题:
所以我的问题是;为什么两个版本的jQuery在结果上有所不同?我在版本文档中找不到任何看起来像是会导致jQuery的两个版本之间行为不同的东西。
我很高兴对此有任何见识,对我有启发。
最佳答案
jQuery v2的Deferred和Promise不符合Promises / A +规范(部分是因为它们早于当前版本),并且不能与本机Promises可靠地互操作。 jQuery v3 fixed them,因此它们可以与本机promise互操作。 (尽管$.when
并不完全兼容。)
另外:如果您要处理本机承诺,我建议尽量远离$.when
。请改用Promise.all
。 :-)实际上,我的偏好是要么完全停留在jQuery Deferred / Promise生态系统之内,要么完全停留在它之外(通过尽早将所有jQuery Deferreds / Promises转换为真实的)。
这是$.when
不能使用本机Promise的一个更简单的示例。
jQuery v2,不起作用:
function timeout(value, delay) {
console.log("creating promise for " + value);
return new Promise(resolve => {
setTimeout(() => {
console.log("resolving promise for " + value);
resolve(value);
}, delay);
});
}
$.when(
timeout(1, 100),
timeout(2, 200),
timeout(3, 300)
).then(result => {
console.log("then on $.when: ", result);
});
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
jQuery v3,可以工作,但请注意返回值只是第一个promise的值(因为
$.when
对then
回调的调用是非标准的:它将每个promise结果作为离散参数传递):function timeout(value, delay) {
console.log("creating promise for " + value);
return new Promise(resolve => {
setTimeout(() => {
console.log("resolving promise for " + value);
resolve(value);
}, delay);
});
}
$.when(
timeout(1, 100),
timeout(2, 200),
timeout(3, 300)
).then(result => {
console.log("then on $.when: ", result);
});
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
旁注:没有必要在
new Promise
中使用getSeriesDescription
,getSeriesNotes().then
已经向您保证可以使用。有趣的是,如果您解决了该问题,它甚至可以在jQuery v2中使用:format(function(r) {
console.log('Done!', r);
});
function format(callback) {
var promises = [];
var items = [{
model: 'George'
}];
$.each(items, function(i, item) {
var selectedSeries = item.model;
promises.push(getSeriesDescription(selectedSeries));
});
$.when.apply($, promises).then(function(seriesInfo) {
console.log('Calling back');
callback(seriesInfo);
});
}
function getSeriesDescription(series) {
return getSeriesNotes().then(function(notes) {
console.log('Processing Notes...');
var rNotes;
$.each(notes.data, function() {
if (series !== 'undefined') {
console.log('Checking series ' + this.first_name + ' against ' + series + '...');
if (this.first_name == series) {
console.log('Series found!');
rNotes = this;
return false;
}
}
});
if (rNotes !== undefined) {
console.log('Returning series specific notes...');
return rNotes;
} else {
return notes;
}
});
}
function getSeriesNotes() {
return $.ajax({
url: 'https://reqres.in/api/users?delay=2',
dataType: 'json',
type: 'GET',
data: '',
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
关于javascript - 在jQuery 2.1(而非3.1)中解决了 promise 之前,返回了多个 promise 之后的回调,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50863790/