2017-12-01 2 views
0

Firebase에 저장된 토큰 배열을 반환하려고하는데 'promise'를 사용하고 있습니다.'promise'는 빈 배열을 반환합니다.

function getUsersTokens() { 
let dbRef = db.ref('/system/users'); 
let result = new Promise((resolve, reject) => { 
    dbRef.once('value', (snap) => { 
     let tokens = []; 
     snap.forEach(child => { 
      if(child.Status != "occupied"){ 
       helper.getToken(child.key,db).then(function(token){ 
        tokens.push(token); 
       }); 
      }  
     }); 
     resolve(tokens); 
    }, (err) => { 
     reject(err); 
    }); 
}); 
return result; 
    } 

그리고 이것은 "helper"모듈의 'getToken'메소드입니다.

exports.getToken=function(uid,db){ 
    return db.ref(`/Tokens/${uid}`).once('value').then(function(result){ 
    return result.val(); 
    }); 
}; 

문제는 때마다 나는 모든 것이 잘 작동 배열에 토큰 밀어 것입니다,하지만 종료 getUsersTokens()는 배열이 빈 얻을 때.

도움 주셔서 감사합니다.

답변

2

문제는 helper.getToken() 비 차단, 그래서 당신의 forEachtokens에 자신의 토큰을 밀어 완료 한 getToken() 모든 호출하기 전에 실행 완료됩니다 때문에 result 약속을 너무 일찍 해결된다는 것이다.

좀 더 쉽게하려면 result 약속을 두 가지 약속으로 나눌 수 있습니다. 첫 번째 약속은 snap을 담당 할 것입니다. 두 번째 약속은 토큰의 배열을 생산하는 snap을 통해 반복하는 담당하게됩니다

function getUsersTokens() { 

    let dbRef = db.ref('/system/users'); 

    let result = new Promise((resolve, reject) => { 
     dbRef.once('value', (snap) => { 
      resolve(snap); 
     }, (err) => { 
      reject(err); 
     }); 
    }); 

    return result.then(snap => { 

     let prommiseArr = []; 

     snap.forEach(child => { 
      if(child.Status != "occupied"){ 
       let p = helper.getToken(child.key,db); 
       promiseArr.push(p); 
      } 
     }); 

     return Promise.all(promiseArr); // resolves to array of tokens 

    }); 
} 

Promise.all는 약속의 배열에 걸리고, 그 약속도 모두 해결 한 경우 해결합니다. 각 약속이 promiseArr으로 토큰으로 해석되기 때문에 getUsersToken에 의해 반환 된 약속에는 궁극적으로 토큰 배열이 포함됩니다.

1

getToken()이 해결되기 전에 약속이 토큰 배열로 해결 되었기 때문에 발생합니다. 토큰이 도착하기 전에 핸들러가 실행되기 때문에 빈 배열을 볼 수 있습니다.

해결하기 전에 기다려야합니다. 이 같은 지적

function getUsersTokens() { 
 
    let dbRef = db.ref('/system/users'); 
 
    return new Promise((resolve, reject) => { 
 
    dbRef.once('value', (snap) => { 
 
     const tokensPromise = snap 
 
     .filter(child => child.Status !== "occupied") 
 
     .map(child => helper.getToken(child.key, db)); 
 
     resolve(Promise.all(tokensPromise)); 
 
    }); 
 
    }); 
 
}

0

Promise.all을 그대로 @ 여기에 완벽 앙드레 Werlang 및 @Christian 산토스 사용하는 예제는 방법

가 이
+0

가 작동하지 않을

function getUsersTokens() { let dbRef = db.ref('/system/users'); let result = new Promise((resolve, reject) => { dbRef.once('value', (snap) => { snap.reduce((chain, child) => { return chain.then(array => { return helper.getToken(child.key,db).then(function(token){ return array.push(token); }); }); }, Promise.resolve([])).then(tokens=>{ resolve(tokens); }); }, (err) => { reject(err); }); }); return result; } 
줄일 수있다 나중에 토큰이 배열에 푸시되기 때문입니다. 또한 Promise.resolve ([])는 까다 롭고 약속을 해결하는 것이 즉각적인 것이 아니라는 사실에 의존합니다. –

관련 문제