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

时间:2018-06-14 18:30:16

标签: javascript jquery ajax promise

问题:

我一直在试图找出为什么我使用$ .when.apply()。then()来编写一些代码来解决多个promises,然后返回数据似乎触发不同步返回一个未解决的promise,然后在调用callback之后解析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版本的结果。下面我有两个完全相同的代码的小提琴,不同版本的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返回系列特定注释......

     

(index):46回电

     

(指数):31完成! {id:1,first_name:“George”,last_name:“Bluth”,avatar:“https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg”}

版本2.1.3首先返回最后两行,然后按照我期望的顺序返回其他所有行。

问题:

所以我的问题是;为什么两个版本的jQuery之间的结果有差异?我无法在看到我的版本文档中找到任何内容,因为它会导致两个版本的jQuery之间的行为差​​异。

我很欣赏对自己的启发有任何见解。

1 个答案:

答案 0 :(得分:3)

jQuery v2&#39> s Deferred和Promise不符合Promises / A +规范(部分原因是它们先于当前版本),并且与本机Promise不可靠地互操作。 jQuery v3 fixed them因此它们可以与本机承诺互操作。 (虽然$.when并非完全兼容。)

另外:如果您正在处理原生承诺,我建议尽可能远离$.when。请改用Promise.all。 :-)事实上,我的偏好要么完全保留在jQuery Deferred / promise生态系统内,要么完全保留在它之外(通过将任何jQuery Deferreds / Promises转换为实际的早期)。

这是$.when没有使用原生承诺的一个相当简单的例子。

jQuery v2,无法正常工作:

&#13;
&#13;
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);
});
&#13;
.as-console-wrapper {
  max-height: 100% !important;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

jQuery v3,虽然注意到返回值只是第一个promise的值(因为$.whenthen回调的调用是非标准的:它会传递每个将结果作为离散参数承诺):

&#13;
&#13;
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);
});
&#13;
.as-console-wrapper {
  max-height: 100% !important;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

附注:new PromisegetSeriesDescription没有理由,getSeriesNotes().then 已经为您提供了可以使用的承诺。有趣的是,如果你修复它,它甚至可以在jQuery v2中运行:

&#13;
&#13;
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: '',
  });
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;