2016-08-08 13 views
1

私は、ネストされた約束レイアウトの周りを囲むのに苦労しています。次のように私の現在のコードは次のとおりです。ネストされた約束で構築された1つのオブジェクトを返す

ルータ

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

あなたが見ることができるように、ルータは、イベントに関する情報を取得するための呼び出しを開始します。この関数はデータベース呼び出しを行い、イベントデータを取得します。その後、別のテーブルからイベントのユーザーとホストを取得し、その情報をイベントオブジェクトに追加してから、オブジェクト全体をルータに戻してクライアントに送信する必要があります。

私はgetInfo関数から約束を返さないのでエラーが発生しますが、返すはずの方法や約束がわかりません。

私はこれにいくつかの助けに感謝したいと思います。おかげ

+0

私はベストプラクティスが何であるか(あるいは答えがすでにあるかどう)最後の夜だけで、この問題に遭遇したと好奇心旺盛です。 – ssube

+0

@ssube最も簡単なアプローチは、すべてのデータが収集されたら、約束してコードをラップしてからresolve()を呼び出すことです。私の場合、Promise.all(...)の中からラッパーの約束のためにresolve()を呼び出しました。それはAhmedの答えのように見えます。 –

答えて

1

は、あなたが約束を戻ってきていることを意味します。

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 */) 
    }) 
} 

注:.thenを使用して使用resolvereject代わりreturn

0

それはいくつかの組み合わせですが、主なものは、あなたがgetInfoから何かを返すことはありませんので、あなたのルータハンドラがundefined.thenを呼び出していることです。

.catchthrowなし)は、発信者が消費するために返す予定のPromiseには電話しないでください。これにより、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 
     } 
    }) 
} 
関連する問題