每个循环中的有序 JavaScript Promise
Posted
技术标签:
【中文标题】每个循环中的有序 JavaScript Promise【英文标题】:Ordered JavaScript Promise in each loop 【发布时间】:2016-06-25 12:04:05 【问题描述】:我正在创建一个 XML 文件,同时使用下划线遍历一个数组。在那个循环中,我需要调用一个外部资源来检索一个值,以便为数组中的这个特定项目写入一个 XML 元素。
我很困惑如何从外部资源中检索值,同时保持循环的顺序,以便将值包含在数组中的正确项目中。
我在检索值的函数中返回了一个 Promise,但这显然是不正确的。
import Promise from 'bluebird';
import XMLWriter from 'xml-writer';
import _ from 'underscore';
import request from 'request';
class Tester
writeXml()
let stores = [
StoreId: 1, LocationId: 110,
StoreId: 14, LocationId: 110,
StoreId: 15, LocationId: 110,
];
let xw = new XMLWriter();
xw.startDocument();
xw.startElement('Stores');
// Loop through all the stores to write the XML file.
_.each(stores, (s) =>
xw.startElement('Store')
.startElement('StoreId').text(s.StoreId).endElement()
.startElement('LocationId').text(s.LocationId).endElement()
// Need to call an external resource here to get the
// store code, but unsure how to do this.
this.getStoreCode(s.LocationId, s.StoreId).then((storeCode) =>
xw.startElement('StoreCode').text(storeCode).endElement();
);
xw.endElement();
);
xw.endDocument();
console.log(xw.toString());
getStoreCode(locationId, storeId)
return new Promise((resolve, reject) =>
let apiUrl = 'http://127.0.0.1:3000/api/v1/stores?filter' +
'[where][locationId]=' + locationId +
'&filter[where][storeId]=' + siteId + '&filter[fields][storeCode]=true';
request(apiUrl, (error, response, body) =>
if (!error)
let result = JSON.parse(body);
return resolve(result[0].storeCode);
else
return reject(error);
);
);
new Tester().writeXml();
【问题讨论】:
我猜,你需要先加载你的资源,然后再写xml结构 我同意 webduvet。首先将所有资源加载到 JS 对象中,然后,一旦解决了所有承诺,就编写 xml。 看看Promise.all
。你应该使用map
而不是forEach
【参考方案1】:
未经测试,但这是可行的方法(或者,更谦虚地说,是一种可行的方法)。
writeXml(stores)
let xw = new XMLWriter();
xw.startDocument();
xw.startElement('Stores');
return Promise.map(stores, (store) =>
return this.getStoreCode(store.LocationId, store.StoreId).then((storeCode) =>
store.StoreCode = storeCode;
return store;
);
).each((storeWithStoreCode) =>
xw.startElement('Store');
_.each(['StoreId', 'LocationId', 'StoreCode'], (prop) =>
xw.startElement(prop).text(storeWithStoreCode[prop]).endElement();
);
xw.endElement();
).then(() =>
xw.endDocument();
return xw;
);
和
writeXml([
StoreId: 1, LocationId: 110,
StoreId: 14, LocationId: 110,
StoreId: 15, LocationId: 110,
]).then((xw) =>
console.log(xw.toString());
);
在英语中,这使用Promise.map()
将普通的store
对象投影到具有StoreCode
属性的存储对象的Promise 中。
之后,.each()
将依次写入 XML 写入器。
最后整个链解析为 XML writer 对象本身,您可能希望将其更改为不同的结果。
使用 Promise 的函数应该返回一个 Promise(或调用某种回调),以便调用代码有机会知道该函数何时完成。
【讨论】:
是否允许省略匹配xw.startElement('Stores')
的xw.endElement()
?
@Roamer-1888 我不确定。直觉上我本以为 endDocument()
会隐式结束所有打开的元素,但我还没有测试过(或查过)。
@duffn 不要忘记error management,在适当的地方。不定义错误行为并不理想。
@Tomalak,here 的例子表明了这一点。顺便说一句,干得好。以上是关于每个循环中的有序 JavaScript Promise的主要内容,如果未能解决你的问题,请参考以下文章
[万字详解]JavaScript 中的异步模式及 Promise 使用