我正在使用Axios / promises来发出AJAX请求,但结构有点令人困惑。基本上我希望这种情况发生:
masterlist.xml
。category.xml
。manifest.xml
并解析数据。示例结构:
masterlist.xml
<master>
<category>action</category>
<category>romance</category>
</master>
类别XML(例如action.xml和romance.xml)
<manifestUrls>
<manifest>foo/bar/manifest.xml</manifest>
<manifest>alice/bob/manifest.xml</manifest>
<manifest>hello/world/manifest.xml</manifest>
</manifestUrls>
显示XML
<manifest>
<data>Blah blah blah</data>
<manifest>
我对如何将此结构化为具有then
的Axios请求感到困惑。我希望有三个函数getMaster()
,getCategory(url)
和getManifest(url)
最好是独立的(例如getMaster
不必直接调用getCategory
),但似乎可能是必要的。
如何在Axios中构建这个结构?
答案 0 :(得分:3)
承诺的主要好处之一是它们可以让您轻松避免方法之间的相互依赖。
以下是如何做到这一点的大致概述。
// put it all together
getMaster()
.then(parseMaster)
.then(function (categories) {
return Promise.all(categories.map(getAndParseCategory));
})
.then(flatten) // the previous then() resolves to an array-of-arrays
.then(function (manifestUrls) {
return Promise.all(manifestUrls.map(getManifest));
})
.then(function (manifests) {
// manifests is an array of all manifests
});
// Examples of what each of the functions used above would do
function getMaster() {
return axios.get('masterUrl')
.then(function (response) { return response.data; });
}
function parseMaster(masterContent) {
// parse and return an array of categories
}
function getCategory(name) {
var url = // ... build the URL based on the name
return axios.get(url)
.then(function (response) { return response.data; });
}
function parseCategory(categoryContent) {
// parse and return an array of URLs synchronously for one category
}
function getAndParseCategory(name) {
return getCategory(name).then(parseCategory);
}
function getManifest(url) {
return axios.get(url)
.then(function (response) { return response.data; });
}
function flatten(arrayOfArrays) {
return [].concat.apply([], arrayOfArrays);
}
如果您正在使用Bluebird或其他为承诺提供.map()
方法的东西,那么您可以稍微整理一下这个管道:
// using Promise.resolve() at the beginning to ensure
// the chain is based of the desired kind of promise
Promise.resolve()
.then(getMaster)
.then(parseMaster)
.map(getCategory)
.map(parseCategory)
.then(flatten) // previous line resolves to an array-of-arrays
.map(getManifest)
.then(function (manifests) {
// manifests is an array of all manifests
});
当然,如果您不想导入整个第三方承诺库,也可以定义自己的.map
方法:
if (!Promise.prototype.map) {
Promise.prototype.map = function (func) {
return this.then(function (result) {
return Promise.all(result.map(func));
});
};
}
修改:在下面的评论中回答您的问题。如果您想传递类别文本以便它可以包含在清单URL中,我认为一种干净的方法是将其包含在getCategory()
返回的数据中,以便parseCategory
可以利用它。其他一切都可以保持不变。
示例:
function getCategory(name) {
var url = // ... build the URL based on the name
return axios.get(url)
.then(function (response) {
return {
name: name,
data: response.data
};
});
}
function parseCategory(categoryContent) {
var urls = // parse URLs from categoryContent.data
return urls.map(function (url) {
return categoryContent.name + '/' + url;
});
}