2016-08-08 2 views
1

중첩 된 약속 레이아웃에서 내 머리를 감싸는 데 어려움을 겪고 있습니다. 다음과 같이 내 현재 코드는 다음과 같습니다중첩 된 약속으로 빌드 된 하나의 객체 반환

라우터 당신이 볼 수 있듯이, 라우터 이벤트에 대한 정보를 얻을 수있는 호출을 시작

getInfo(id) { 
    db.main('events').where('id', id).select() 
    .then((result) => { 
     if(result.length > 0) { 
      var event = result[0]; 

      //regular functions 
      event.status = this.getStatus(id); 
      event.content = this.getContent(id); 
      event.price = this.getPrice(id); 

      //promise functions 
      var users = this.getUsers(id); 
      var hosts = this.getHosts(id); 

      Promise.all([users, hosts]).then(values => { 
       event.users = values[0]; 
       event.hosts = values[1]; 

       //return whole event object to router 
       return event; 
      }) 
      .catch((err) => { 
       return { 
        result: 'error', 
        error: err 
       }; 
      }); 

     } else { 
      return { 
        result: 'error', 
        error: "Event does not exist" 
       }; 
     } 
    }).catch((e) => { 
     return { 
        result: 'error', 
        error: "Could not retrieve event info" 
       }; 
    }); 
} 

router.get(`/${config.version}/event/:id?`, function (req, res, next) { 
    var event = new Event(req, res, next); 
    event.getInfo(req.params.id).then((info) => { 
     res.send(info); 
    }); 
}); 

기능. 이 함수는 데이터베이스 호출을 수행하고 이벤트 데이터를 가져옵니다. 그 후에 다른 테이블에서 이벤트의 사용자와 호스트를 가져와 해당 정보를 이벤트 객체에 추가 한 다음 전체 객체를 라우터로 보내 클라이언트로 보냅니다.

getInfo 함수에서 약속을 반환하지 않기 때문에 오류가 발생하지만 반환 할 약속이나 방법이 확실하지 않습니다.

감사합니다. 감사합니다

+0

나는 지난 밤에이 문제에 부딪쳤으며 모범 사례가 무엇인지 궁금합니다 (이미 답변이있는 경우). – ssube

+0

@ssube 가장 쉬운 방법은 약속을 사용하여 코드를 래핑 한 다음 모든 데이터가 수집되면 resolve()를 호출하는 것입니다. 제 경우에는 Ahmed의 답변에서 볼 수 있듯이 Promise.all (...) 내에서 wrapper 약속에 대한 resolve()를 호출했습니다. –

답변

1

.then 당신이 약속을 반환하는 것을 의미한다 사용.

function getInfo(id) { 
    return new Promise(function(resolve, reject) { 
    resolve('yay!'); 
    }) 
} 
getInfo().then(function(result) { //result = yay! }); 

, 당신의 코드가 작동을 단순히 모든 결의로 복귀 거부와 오류를 교체하고 내가했던 같은 return new Promise으로 전체를 포장합니다.

getInfo(id) { 
 
    return new Promise(function(resolve, reject) { 
 
    db.main('events').where('id', id).select() 
 
     .then((result) => { 
 
     if (result.length > 0) { 
 
      var event = result[0]; 
 

 
      //regular functions 
 
      event.status = this.getStatus(id); 
 
      event.content = this.getContent(id); 
 
      event.price = this.getPrice(id); 
 

 
      //promise functions 
 
      var users = this.getUsers(id); 
 
      var hosts = this.getHosts(id); 
 

 
      Promise.all([users, hosts]).then(values => { 
 
       event.users = values[0]; 
 
       event.hosts = values[1]; 
 

 
       //return whole event object to router 
 
       resolve(event); 
 
      }) 
 
      .catch((err) => { 
 
       reject({ 
 
       result: 'error', 
 
       error: err 
 
       }); 
 
      }); 
 

 
     } else { 
 
      reject({ 
 
      result: 'error', 
 
      error: "Event does not exist" 
 
      }); 
 
     } 
 
     }).catch((e) => { 
 
     reject({ 
 
      result: 'error', 
 
      error: "Could not retrieve event info" 
 
     }); 
 
     }); 
 
    }); 
 
}

+1

'db.main(). select(). then()'이 이미 약속이라면, 방금 반환 할 수있는 약속을 이미 가지고있을 때 약속을 다른 것으로 포장하는 것은 반대 패턴입니다. 이 코드는 훨씬 더 간단합니다. – jfriend00

+0

우리는 이것이 그것이 약속임을 어떻게 알 수 있습니까? 또는'.then'을 가지고 있다면 약속 한 것을 돌려 주는가? – Bamieh

+0

사용중인 데이터베이스의 문서를 읽거나 코드를보고 실제로 약속과 비슷한 동작이 있는지 확인하십시오. 현재 대부분의 DB는 약속 옵션을 내장하고 있습니다. 왜냐하면이 옵션을 사용하는 것이 훨씬 더 나은 방법이기 때문입니다. '.then()'은 약속을 암시하지만 약속 준수가 아닌 모조품이 있기 때문에 실제 약속인지 알아볼 가치가 있습니다. – jfriend00

0

그냥 같이 약속에 비동기 코드를 포장 :

getInfo(id) { 
    return new Promise(function(resolve, reject) { 
    db.main('events').where('id', id).select() 
    .then((result) => { 
     //... 
     resolve(/* result */) 
     // OR 
     reject(/* Error */) 
    }) 
} 

참고 : 사용 resolvereject 대신 return

0

그것은 몇 가지의 조합이지만, 주요 하나는 결코 그렇게 라우터 핸들러가 undefined.then를 호출, getInfo 아무것도 반환하지 않습니다 것입니다.

호출자가 사용하기 위해 반환하려는 Promise.catch (throw없이 입력)을 호출하지 마십시오. 따라서 Promise 체인을 복구 된 것으로 복구 했으므로 .catch을 사용할 수 없습니다.

.then 안에 무엇을 반환해도 약속 체인에 병합되므로 실제로 "약속으로 해결되는 약속"이 아닙니다. 전체 코드를 다음으로 대체 할 수 있습니다 :

getInfo (id) { 
    return db.main('events').where('id', id).select() 
    .then(result => { 
     if (result.length == 0) { 
      // you can also just throw your error object thing, 
      // but standard Error are generally the convention 
      throw new Error('Event does not exist') 
     } 

     const [event] = result 

     event.status = this.getStatus(id) 
     event.content = this.getContent(id) 
     event.price = this.getPrice(id) 

     return Promise.all([this.getUsers(id), this.getHosts(id)]) 
     .then(([users, hosts]) => { 
      event.users = users 
      event.hosts = hosts 

      // this is the only value that 
      // this.getInfo(id).then(value => {/* ... */}) will see 
      return event 
     } 
    }) 
}