对多个请求使用一个 iron-ajax 元素



理论上,通过设置auto属性,然后在元素上重复设置url属性,应该可以将一个iron-ajax元素用于多个请求。iron-ajax有一个名为activeRequests的属性,它是一个只读数组,因此它似乎支持同时排队多个请求。然而,在实践中,它似乎不起作用。

例如,在下面的 JS Bin 中,我检索了包含单词polymer的书籍的书籍 ID 列表,然后使用for循环重复设置url的值。

<!doctype html>
<html>
<head>
<meta name="description" content="single iron-ajax for multiple requests">
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script href="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-ajax/iron-ajax.html" rel="import">
</head>
<body>
<dom-module id="my-el">
<template>
<iron-ajax id="ajax"
url="https://www.googleapis.com/books/v1/volumes?q=polymer"
handle-as="json"
on-response="onResponse"
last-response="{{response}}" auto></iron-ajax>
</template>
<script>
Polymer({
is: 'my-el',
properties: {
response: {
type: Object,
notify: true
}
},
onResponse: function(e) {
var ajax = this.$.ajax;
var originalUrl = 'https://www.googleapis.com/books/v1/volumes?q=polymer';
var url = ajax.lastRequest.xhr.responseURL;
if (url.includes(originalUrl)) {
console.log('this is the first request');
for (var i = 0; i < ajax.lastResponse.items.length; i++) {
ajax.url = this.url(ajax.lastResponse.items[i].id);
}            
} else {
console.log(ajax.lastResponse.selfLink);
}
},
url: function(id) {
return "https://www.googleapis.com/books/v1/volumes/" + id;
}
});
</script>
</dom-module>
<my-el></my-el>
</body>
</html>

确实可以将iron-ajax用于多个请求,但不能启用auto,否则您将击中iron-ajax的去抖动器。来自 聚合物文档iron-ajax

auto设置为true时,每当元素的urlparamsbody属性发生变化时,元素都会执行请求。如果多个属性按顺序更改,自动生成的请求将被取消退回。

在您的问题代码中:

// template
<iron-ajax auto ...>
// script
onResponse: function(e) {
...
for (var i = 0; i < ajax.lastResponse.items.length; i++) {
ajax.url = this.url(ajax.lastResponse.items[i].id);
}
}

。您可能期望iron-ajax为每个 URL 生成一个新请求,但 Debouncer 将请求折叠为一个(仅接受最后一次调用)。

还值得注意的是:response处理程序的事件详细信息(即e.detail)是相应的iron-request,其中包含AJAX响应(即e.detail.response)。使用事件详细信息是可取的,因为它避免了来自iron-ajax的同时请求中的争用条件,其中this.$.ajax.lastResponsethis.$.ajax.lastRequest被异步覆盖。

onResponse: function(e) {
var request = e.detail;
var response = request.response;
}

要在新 URL 中重复使用iron-ajax,请禁用auto(这将禁用去抖动器)并在更新 URL 后手动调用generateRequest()。这将允许多个同时的异步请求(并且activeRequests将填充多个请求)。

// template
<iron-ajax ...>   <!-- no 'auto' -->
// script
onResponse: function(e) {
var request = e.detail;
var response = request.response;
...
for (var i = 0; i < response.items.length; i++) {
ajax.url = this.url(response.items[i].id);
ajax.generateRequest();
}
},
ready: function() {
this.$.ajax.generateRequest(); // first request
}

下面是代码的修改版本:

<head>
<base href="https://polygit.org/polymer+1.5.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-ajax/iron-ajax.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<!-- We're reusing this iron-ajax to fetch more data
based on the first response, and we don't want
iron-ajax's debouncer to limit our requests,
so disable 'auto' (i.e., remove the attribute
from <iron-ajax>). We'll call generateRequest()
manually instead.
-->
<iron-ajax id="ajax"
url="https://www.googleapis.com/books/v1/volumes?q=polymer"
handle-as="json"
on-response="onResponse"
on-error="onError">
</iron-ajax>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
onError: function(e) {
console.warn('iron-ajax error:', e.detail.error.message, 'url:', e.detail.request.url);
},
onResponse: function(e) {
var ajax = this.$.ajax;
var originalUrl = 'https://www.googleapis.com/books/v1/volumes?q=polymer';
var url = e.detail.url;
if (url.includes(originalUrl)) {
var books = e.detail.response.items || [];
console.log('this is the first request');
for (var i = 0; i < books.length && i < 3; i++) {
ajax.url = this.url(books[i].id);
console.log('fetching:', ajax.url);
ajax.generateRequest();
}
} else {
var book = e.detail.response;
console.log('received:', e.detail.url, '"' + book.volumeInfo.title + '"');
}
},
url: function(id) {
return "https://www.googleapis.com/books/v1/volumes/" + id;
},
ready: function() {
// generate first request
this.$.ajax.generateRequest();
}
});
});
</script>
</dom-module>
</body>

https://jsbin.com/qaleda/edit?html,console

我不知道activeRequests属性是怎么回事,但我能够通过稍微重组我的代码来让它工作。基本上,只需实现一个队列,然后从队列中弹出一个项目,并在最后一个请求完成后设置url

<!doctype html>
<html>
<head>
<meta name="description" content="http://stackoverflow.com/questions/37817472">
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script href="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-ajax/iron-ajax.html" rel="import">
</head>
<body>
<dom-module id="my-el">
<template>
<iron-ajax id="ajax"
url="https://www.googleapis.com/books/v1/volumes?q=polymer"
handle-as="json"
on-response="onResponse"
last-response="{{response}}" auto></iron-ajax>
</template>
<script>
Polymer({
is: 'my-el',
properties: {
response: {
type: Object,
notify: true
},
queue: {
type: Array,
notify: true,
value: function() { return []; }
}
},
onResponse: function(e) {
var ajax = this.$.ajax;
var originalUrl = 'https://www.googleapis.com/books/v1/volumes?q=polymer';
var url = ajax.lastRequest.xhr.responseURL;
if (url.includes(originalUrl)) {
console.log('this is the first request');
for (var i = 0; i < ajax.lastResponse.items.length; i++) {
this.push('queue', ajax.lastResponse.items[i].id);
}
ajax.url = this.url(this.pop('queue'));
} else {
console.log(ajax.lastResponse.selfLink);
ajax.url = this.url(this.pop('queue'));
}
},
url: function(id) {
return "https://www.googleapis.com/books/v1/volumes/" + id;
}
});
</script>
</dom-module>
<my-el></my-el>
</body>
</html>

https://jsbin.com/beyawe/edit?html,console

您可以尝试 iron-multiple-ajax-behavior。 让我知道这是否对您有用。

最新更新