.then 的 Promise.all 没有执行
Posted
技术标签:
【中文标题】.then 的 Promise.all 没有执行【英文标题】:.then of Promise.all not executing 【发布时间】:2018-07-25 21:01:06 【问题描述】:我正在使用 Firestore 检索具有以下 DS 的数据。 我有一个 Company 集合,其中包含一个子集合 Branches 所以我试图检索列出所有 Companies 及其 Branches
代码:
exports.findAll = function (req, res)
getcompanies().
then((companies) =>
console.log("Main "+ companies) // info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
return res.json(companies);
)
.catch((err) =>
console.log('Error getting documents', err);
);
function getCompanies()
var companiesRef = db.collection('companies');
return companiesRef.get()
.then((snapshot) =>
let companies = [];
return Promise.all(
snapshot.forEach(doc =>
let company = ;
company.id = doc.id;
company.company = doc.data();
var branchesPromise = getBranchesForCompanyById(company.id);
return branchesPromise.then((branches) =>
company.branches = branches;
companies.push(company);
if(snapshot.size === companies.length)
console.log("companies - Inside" + JSON.stringify(companies)); //This prints all companies with its branches
return Promise.resolve(companies);
)
.catch(err =>
console.log("Error getting sub-collection documents", err);
return Promise.reject(err);
)
)
)
.then(companies =>
console.log("Outside " + companies) // This is never executed
return companies;
)
.catch(err =>
return err;
);
)
.catch(err =>
return err;
);
function getBranchesForCompanyById(id)
var branchesRef = db.collection('companies').doc(id).collection('branches');
let branches = [];
return branchesRef.get()
.then(snapshot =>
snapshot.forEach(brnch =>
let branch = ;
branch.id = brnch.id;
branch.branch = brnch.data();
branches.push(branch);
)
return branches;
)
.catch(err =>
return err;
)
我现在已经有了所有需要的数据。
console.log("companies - Inside" + JSON.stringify(companies)); //This prints all companies with its branches
但是 Promise.all 的 then 永远不会被执行。所以得到这个错误 -
info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
console.log("Main "+ companies) // info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
我觉得我已经遵循了这里指定的所有规则:https://***.com/a/31414472/2114024 关于嵌套承诺,不知道我在哪里漏掉了重点。 提前致谢!
【问题讨论】:
【参考方案1】:根据 Evert 和 Rahul 的意见,感谢你们两位,我已经解决了这里的问题。
-
我处理了 catch 块中的所有错误
Promise.all 没有返回任何内容,因此我将 forEach 转换为 map。
所以这是我更新的代码,它解决了问题:
exports.findAll = function (req, res)
getcompanies().
then((companies) =>
console.log("Main " + companies) // Prints all companies with its branches
return res.json(companies);
)
.catch((err) =>
console.log('Error getting documents', err);
return res.status(500).json( message: "Error getting the all companies" + err );
);
function getCompanies()
var companiesRef = db.collection('companies');
return companiesRef.get()
.then((snapshot) =>
let companies = [];
return Promise.all(
snapshot.docs.map(doc =>
let company = ;
company.id = doc.id;
company.company = doc.data();
var branchesPromise = getBranchesForCompanyById(company.id);
return branchesPromise.then((branches) =>
company.branches = branches;
companies.push(company);
if (snapshot.size === companies.length)
console.log("companies - Inside" + JSON.stringify(companies));
return companies;
)
.catch(err =>
console.log("Error getting sub-collection documents", err);
throw new Error(err);
)
)
)
.then(companies =>
console.log("Outside " + companies); // Executed now
return companies[companies.length - 1];
)
.catch(err =>
throw new Error(err);
);
)
.catch(err =>
throw new Error(err);
);
function getBranchesForCompanyById(id)
var branchesRef = db.collection('companies').doc(id).collection('branches');
let branches = [];
return branchesRef.get()
.then(snapshot =>
snapshot.forEach(brnch =>
let branch = ;
branch.id = brnch.id;
branch.branch = brnch.data();
branches.push(branch);
)
return branches;
)
.catch(err =>
throw new Error(err);
)
【讨论】:
SO 应该允许您接受自己的答案。这样做是完全可以接受的。【参考方案2】:在您的代码中,您可以使用 map 而不是 forEach。 Promise.all 接受一个承诺数组,但 forEach 不返回一个数组
return Promise.all(
snapshot.map(doc =>
let company = ;
company.id = doc.id;
company.company = doc.data();
var branchesPromise = getBranchesForCompanyById(company.id);
return branchesPromise.then((branches) =>
company.branches = branches;
companies.push(company);
if (snapshot.size === companies.length)
console.log("companies - Inside" + JSON.stringify(companies)); //This prints all companies with its branches
return Promise.resolve(companies);
)
.catch(err =>
console.log("Error getting sub-collection documents", err);
return Promise.reject(err);
)
)
)
【讨论】:
我试过了,我认为,快照不支持地图。会再试一次看看。谢谢! 不需要返回 Promise.resolve(companies);您可以直接返回公司【参考方案3】:我发现至少有 2 个问题:
forEach 可能不会返回任何内容,您将 forEach 的结果发送到Promise.all()
。
如果 Promise.all() 抛出异常,您的一些 catch
处理程序只会抓取错误并返回它。归还它会将其变为非异常。
您实际上也不必为每个 Promise 链添加 catch
,只要将 Promise 链的结果反馈到另一个 Promise 链,您可能只需要 1 个 catch 块。
您的then()
函数之一也不应该嵌套得那么深。只需将其提升一个级别,这就是承诺的意义所在。
【讨论】:
感谢您的意见。我已经更新了问题,我得到了一个 -info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined。我仍然会根据您的输入重构代码。再次感谢! _你也真的不必为每一个 Promise 链添加一个 catch,只要你将一个 Promise 链的结果反馈给另一个 Promise 链,你可能只需要 1 个 catch 块_回复为此:Firestore 强制处理每个 promise 调用。 如果你在后面有一个 catch 块,你仍然会处理每个 promise 调用。我绝对同意每个 Promise 链必须有一个 catch 块,但只要你不断返回 Promise 的结果,你最终只需要一个。这绝对是可能的情况之一。;以上是关于.then 的 Promise.all 没有执行的主要内容,如果未能解决你的问题,请参考以下文章
React Native 为啥我的代码在完成任务之前执行? Promise.all().then() 异步问题
.then() 在嵌套的 promise.all 和 fetch 完成之前执行
使用 Promise.all() 在 Promise 实现时执行操作