问题:
我一直在用头撞墙试图弄清楚为什么我使用 $.when.apply().then() 编写的一些代码来解决多个 promise 然后返回数据似乎不同步,返回 Unresolved promise ,然后在调用回调后解决 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 版本的结果。下面我有两个具有完全相同代码的 fiddle ,具有不同版本的 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 版本则没有。
预期结果:
Processing Notes...
(index):58 Checking series George against George...
(index):60 Series found!
(index):67 Returning series specific notes...
(index):46 Calling back
(index):31 Done! {id: 1, first_name: "George", last_name: "Bluth", avatar: "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
并不完全兼容。)
另外:如果您正在处理 native promise ,我建议尽可能远离 $.when
。请改用 Promise.all
。 :-) 事实上,我的偏好是要么完全留在 jQuery Deferred/promise 生态系统中,要么完全处于其外部(通过尽早将任何 jQuery Deferred/Promises 转换为真实的)。
这是一个相当简单的 $.when
不使用原生 promises 的例子。
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>
旁注:getSeriesDescription
中没有理由 new Promise
,getSeriesNotes().then
已经 给出你可以使用的 promise 。有趣的是,如果你解决了这个问题,它甚至可以在 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 中解决 promise 之前返回多个 promise 后的回调,但不是 3.1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50863790/