Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript承诺绕过解析并继续执行.then()_Javascript_Firebase_Asynchronous_Firebase Realtime Database_Promise - Fatal编程技术网

JavaScript承诺绕过解析并继续执行.then()

JavaScript承诺绕过解析并继续执行.then(),javascript,firebase,asynchronous,firebase-realtime-database,promise,Javascript,Firebase,Asynchronous,Firebase Realtime Database,Promise,我在嵌套承诺方面遇到了一些问题,这导致了忘记承诺的问题 let promiseList = new Promise((resolve, reject) => { //first query to retrieve from firebase query.once( 'value', data => { var promises = []; data.forEach(snapshot => {

我在嵌套承诺方面遇到了一些问题,这导致了忘记承诺的问题

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);
}   
});
我设法用“inside promise”从console.log打印出数据。然而,当我试图从打印出来。然后,没有显示任何内容

现在的问题是它实际上运行了。然后在我解决承诺之前


有什么想法吗?

我从未使用过Firebase,但我知道承诺。 检查此示例链接承诺,注意生成链接的返回语句

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)  
});

承诺不是这样起作用的,很少有人需要把它们嵌套起来。如果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); }, []));
现在您有了一个包含值数组的结果承诺。然后,您可以调用它并对其进行迭代:

result.then(arr => arr.forEach(x => console.log(x.branchName)));

为什么要筑巢?这完全没有必要。你有没有尝试过使用promises.pushpromise。然后呢?我想做的是首先得到一个收据项目的列表。然后,对于每个收据项目,我都会得到它的详细信息,比如receiptID。然后,我继续根据receiptID查找分支详细信息。有了这些,我就有了嵌套的承诺。我不知道如何真正分开them@CameloCatafarno你是说把它放在后面,然后呢?但我认为你应该先把它推到数组中?你把它推到数组中,然后在没有传递新承诺的情况下将它进一步链接到数组中。然后创建数组。两项中只有一项需要通过。此外,没有任何东西返回到。那么,它不会等待里面的东西完成。为什么?请解释一下,不,请告诉我。我也不确定另一个人。不管怎样,所有的答案都被否决了。@EmmaHannah,一个好的经验法则是不要筑巢:这是承诺应该解决的问题之一。请记住,正如莱昂纳多·查亚(Leonardo Chaia)所指出的,在a中返回一个值,然后返回该值的承诺。还请记住,您可以返回一个数组,然后在链的下一步中使用它。另一个好的经验法则是不要在链中的任何一个步骤中做太多,这会使测试和调试更加困难。@JaredSmith Cool非常感谢您的帮助!但是.map和.filter做什么呢?要将相关数据映射到一起并过滤不必要的数据?@EmmaHannah map接受一个函数并返回将其应用于数组中每个元素的结果。筛选器接受一个函数,并将该函数返回true的数组中的项保留为不起作用的.Nope。在console.log中仍然没有打印任何内容。then@EmmaHannah,检查编辑。顺便说一句,你应该读一些关于。谢谢它的作品!让我试着去理解它是如何工作的。所以基本上你创建了一个outerPromise来包装所有其他的承诺。然后,当您循环遍历每个itemKey时,您创建了一个承诺列表,以获取其详细信息和分支详细信息。之后,您将它们添加到promise数组中。等等,我想我基本上是在读代码。你介意详细解释一下吗?@LeonardoChaia嘿,很抱歉再次打扰你!但假设从第三级承诺开始,我需要获取receiptID并查询另一个account表。我怎样才能做到这一点?我可以从firebase声明一个要查询的新承诺,然后在返回三级承诺时将该承诺推送到承诺数组中吗?