javascript - 在 jQuery 2.1 中解决 promise 之前返回多个 promise 后的回调,但不是 3.1

标签 javascript jquery ajax promise

问题:

我一直在用头撞墙试图弄清楚为什么我使用 $.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 的值(因为 $.whenthen 回调的调用是非-标准:它将每个 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 PromisegetSeriesNotes().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/

相关文章:

javascript - 动态存储未在组合框 extjs 中加载数据

javascript - 如何使用javascript检查可见性属性

javascript - Jquery onclick 似乎阻止了复选框检查

jquery - 删除作品但不隐藏?

javascript - 在iframe中触发 "click"事件

javascript - 在使用 knockout 绑定(bind)的同时使用 AJAX 发布数据

javascript - 如果子 ul 没有可见元素,则隐藏字段集

javascript - lightbox2 模态在部署时不显示图像的问题

javascript - onchange javascript 在 jquerymobile 中提交换行符

jquery - 从 ajax JSON 响应构建数组