我遇到了嵌套承诺的问题,这导致了遗忘的承诺问题。
let promiseList = new Promise((resolve, reject) => {
//first query to retrieve from firebase
query.once( 'value', data => {
var promises = [];
data.forEach(snapshot => {
//get item key
//second query based on item key
var promise = query.once('value');
promises.push(promise);
promise.then(data => {
var itemDetail = data.val();
var receiptID = itemDetail.receiptID;
// third query to find matching receiptID
var query = firebase.database().ref('receipts');
query.once('value', data => {
data.forEach(snapshot => {
snapshot.forEach(childSnapshot => {
if(childSnapshot.key == receiptID){
var branchDetail = childSnapshot.val().branch;
var branchName = branchDetail.branchName;
//console.log('inside promise ' + branchName);
datasetarr.push({branchName: branchName});
}
});
});
});
});
});
// wait till all promises are finished then resolve the result array
Promise.all(promises).then(() => resolve(datasetarr));
});
});
// print out array here
promiseList.then((arr) => {
for(var i = 0; i < arr.length; i++){
console.log(arr[i].branchName);
}
});
我设法使用&#39;内部承诺&#39;打印出console.log中的数据。但是,当我尝试从.then()打印出来时,没有任何显示。
现在的问题是,在我解决诺言之前,它实际上是先运行了.then()。
有什么想法吗?
答案 0 :(得分:1)
我从未使用过Firebase,但我确实知道承诺。
检查此示例链接承诺,请注意产生链接的return
语句。
var outerPromise = query.once('value').then(data => {
// Promise array to group 2nd level promises and then do a Promise.all.
var promises = [];
// This will be the main output of the outerPromise.
// We will populate it asynchronously inside our 2nd level promises.
var datasetarr = [];
data.forEach(snapshot => {
// 2nd level promises, will be appended to the promises array.
// and will be enchained with the 3d level promise.
var promise = query.once('value').then(data => {
var itemDetail = data.val();
var receiptID = itemDetail.receiptID;
var query = firebase.database().ref('receipts');
// Third level promise. It's enchained by the return statement.
return query.once('value').then(data => {
data.forEach(snapshot => {
snapshot.forEach(childSnapshot => {
if(childSnapshot.key == receiptID){
var branchDetail = childSnapshot.val().branch;
var branchName = branchDetail.branchName;
//console.log('inside promise ' + branchName);
datasetarr.push({branchName: branchName});
}
});
});
});
});
promises.push(promise);
});
// We wait until 2nd (and third) level promises are ready
// and the return our desired output, the datasetarr
return Promise.all(promises).then(()=> datasetarr);
});
// Since it's all chained, the outerPromise will resolve once all promises are completed
// and we can get the output we supplied in the last chaining.
outerPromise.then((arr) => {
console.log(arr)
});
答案 1 :(得分:0)
这不是承诺如何运作,很少需要嵌套它们。如果query.once
已经返回了一个很棒的承诺,但是否则你需要将其包裹起来:
let returnsPromise = value => new Promise(res => query.once(value, data => res(data));
同样,如果它已经返回了一个不必要的承诺,但我不是一个火柴人。无论如何,现在你可以这样做:
let result = returnsPromise('value')
// run secondary query based on item key
.then(data => Promise.all(data.map(item => returnsPromise(item.key)))
// now do stuff with those results
.then(data => {
return Promise.all(data.map(item => {
let receiptID = item.val().receiptID;
// Note that the same 'wrap if not already returning promise
// idea' is applicable here, but for illustration I'm just
// going to act like this returns a promise.
// Also note that while I've been rather down on nesting
// its more or less necessary here because you need to capture
// the receipt ID from the surrounding scope.
return firebase.database().ref('receipts')
.once('value')
.then(snapshot => {
return snapshot
.filter(x => x.key === receiptID)
.map(x => {
let branch = x.val().branch.branchName;
return {branch: branch};
});
});
}))
// Now we have an array of arrays of results but we want to
// remove the nesting.
.then(arrayOfArrays => arrayOfArrays.reduce((x,y) => { return x.concat(y); }, []));
现在您有一个包含值数组的结果promise。您可以在其上调用then
并对其进行迭代:
result.then(arr => arr.forEach(x => console.log(x.branchName)));