尝试在循环中等待对象的元素



我正在调用返回字段列表的API。其中一些字段具有相关字段,我还需要查询 API 才能获取这些字段。

所以这是我尝试做的事情(主要是伪代码(:

// gets initial set of fields. This part works.
let fields = await getFields();
processFields(fields).then(data => {
console.log('data now contains object with all fields and related fields', data);
});
async function processFields(fields) {
let fieldObj = {};
return new Promise(resolve => {
fields.forEach(async field => {
if (field.collection) {
let related = await getRelated(field.relatedListFieldType);
fieldObj[field.id] = {
name: field.name,
display: field.display,
fields: related
};
} else {
fieldObj[field.id] = {name: field.name, display: field.display};
}
});
resolve(fieldObj);
});
}
async function getRelated(name) {
… some code here and return promise …
}

我遇到的问题是 因为每个都不等待,所以在第一个控制台.log中,除了具有集合的字段之外,我得到了我期望的所有结果。由于我正在等待这些,因此它永远不会进入返回的字段Obj。如果我不在那里等待,我会在现场得到它们,但是当我把它们打印出来时,它们只是承诺。 我一直在尝试使用 bluebird 和异步 npm 库来尝试获得一个在解析之前等待结果的 foreach,但没有成功,但我没有成功。我能做些什么来度过难关?

使用新代码进行编辑:

async function processFields(data) {
let fieldObj = {};
for (let field of data.data) {
if (field.isCollection) {
let related = await getRelated(field.relatedListFieldType);
fieldObj[field.id] = {
name: field.name,
display: field.display,
fields: related
};
} else {
fieldObj[field.id] = {
name: field.name,
display: field.display
}
}
}
return fieldObj;
}
async function getRelated(name) {
let relatedData = '';
name = name.toLowerCase();
if (objects[name]) {
return objects[name];
} else {
// put a placeholder here so we only request this once
objects[name] = {};
}
return new Promise(resolve => {
let relatedOptions = Object.assign(options, {
path: encodeURI(`/api/objects/v1/${name}/_describe`)
});
let req = https.request(relatedOptions, res => {
res.on('data', chunk => {
relatedData += chunk;
});
res.on('error', err => {
console.log('had error', err);
});
res.on('end', async () => {
objects[name] = await processFields(JSON.parse(relatedData));
resolve(objects[name]);
});
});
req.end();
});
}

使用for,而不是.forEach()来获取循环以等待await.forEach()不是为暂停而设计的await.

也没有理由创建自己的承诺。async函数已经返回了一个承诺,因此您只需使用await,然后返回一个值,该值将自动成为返回的async承诺的解析值。

例如,您可以像这样操作:

async function processFields(fields) {
let fieldObj = {};
for (let field of fields) {
if (field.collection) {
let related = await getRelated(field.relatedListFieldType);
fieldObj[field.id] = {
name: field.name,
display: field.display,
fields: related
};
} else {
fieldObj[field.id] = {name: field.name, display: field.display};
}
}
return fieldObj;
}

fields.forEach不会等待承诺,因此您在任何异步代码完成之前进行解析

用于 ...之

那么也不需要 Promise 构造函数

async function processFields(fields) {
let fieldObj = {};
for (let field of fields) {
if (field.collection) {
let related = await getRelated(field.relatedListFieldType);
fieldObj[field.id] = {
name: field.name,
display: field.display,
fields: related
};
} else {
fieldObj[field.id] = {name: field.name, display: field.display};
}
}
return fieldObj;
}
async function processFields(fields) {
let fieldObj = {};
for(var field of fields) {
if (field.collection) {
let related = await getRelated(field.relatedListFieldType);
fieldObj[field.id] = {
name: field.name,
display: field.display,
fields: related
};
} else {
fieldObj[field.id] = {name: field.name, display: field.display};
}
}
return fieldObj;
}

最新更新