2017-10-20 5 views
1

近代的なJSで遊んで、次のことをちょっと試してみました。入れ子になったPromises.allのアドバイスが必要

HTTP APIとローカルMongoインスタンスを介してExtSystemにアクセスできるようにすることを検討してください。どちらもnameidのオブジェクトを含んでいます。

モンゴのために私はExtSystemからidに等しいsourceIdinternalParamは私のアプリで存在ObjectSchemaモデル({_id, sourceId, name, internalParam})とmongooseを使用しています。

  • ExtSystem.allがIDS [id, id, id]
  • ExtSystem.get戻りが処理できるグローバル関数errHandlerもあり{id, name}

自体をオブジェクトの配列を返す:ExtSystemためrequest.jsプロミスを返す2つの方法がありますrequest.jsmongooseの両方からのエラー。達成する目標は、MongoをExtSystemと同期させることです:MongoのExtSystemのすべてのオブジェクトを更新し、MongoからExtSystemのものを削除します。だから私はまだ4プロミスが解決ネストされた、おそらく何かが欠けてい

ExtSystem.all().then(body => { 
    let basket = []; // will store all promises for both ExtSystem and Mongo requests 
    basket.push(...body.map(o => ExtSystem.get(o.id)); 
    basket.push(ObjectSchema.find({}, 'sourceId')); 

    Promise.all(basket).then(basketDoc => { 
     let mongoObjects = {}, extObjects = {}; 
     basketDoc.pop().forEach(o => mongoObjects[o.sourceId] = o._id); // Mongo retuns array of {_id, sourceId } objects 
     basketDoc.forEach(o => { // ExtSystem returns array of {id, name} objects 
      extObjects[o.id] = { 
       sourceId: o.id, 
       name: o.name 
      } 
     }); 

     let esSet = new Set(Object.keys(extObjects)); 
     let mongoDeleteIds = Object.keys(mongoObjects).filter(oId => !esSet.has(oId)); // Set.has is faster than Array.indexOf 

     let syncPromises = []; 
     syncPromises.push(...Object.keys(extObjects).map(oId => ObjectSchema.findOneAndUpdate({ sourceId: extObjects[oId].sourceId }, extObjects[oId], { upsert: true, new: true }))); 
     syncPromises.push(...mongoDeleteIds.map(oId => ObjectSchema.remove({_id: oId}))); 

     Promise.all(syncPromises).then(_ => { // I don't need results, only the moment when sync is complete 
      ObjectSchema.find().then(doc => { // return actual objects from Mongo 
       someBusinessLogic(doc); 
      }).catch(errHandler); 
     }).catch(errHandler); 
    }).catch(errHandler); 
}).catch(errHandler); 

:私が思いついた何

。あまり複雑でないコードでこれを達成する最善の方法はありますか?

答えて

3

約束は破滅のピラミッドを取り除くために設計されています。あなたがネストされた約束を持っているなら、それは間違っているのです。

プロミスを使用すると、コール内で別の約束を返すことができます。だからではなく、行うので:あなたは、将来の約束にアクセスするために必要ないくつかの変数を持っている場合は

p1.then(stuff => { 
    p2.then(stuff =>{ 
     ... 
    }); 
}); 

をあなたは

p1 
.then(stuff => { 
    return p2; 
}).then(stuff => { 
    return; 
}); 

を行う必要があり、あなたは別の約束としてそれらを含める、またはthis piece of codeを使用することができますいずれかのIしばらく前に作成され、グローバルな再利用可能なオブジェクトを含む約束を作成します。

Promise 
.resolve({})   // creates global object for holding values 
.then(obj => { 
    return pack(obj, taskPromiseA, "a", taskPromiseB, "b"); 
}) 
.then(obj => {  // you can access results from A and B here 
    return pack(obj, taskPromiseC, "c"); 
}) 
.then(console.log); // you can access them all here 
1

プロテイズ​​をチェーンから返すことができます。チェーンできるので、すべてのエラーを1つのハンドラに伝播できます。

あなたのコードは、本質的になる可能性:

ExtSystem.all().then(body => { 
    let basket = []; // will store all promises for both ExtSystem and Mongo requests 
    basket.push(...body.map(o => ExtSystem.get(o.id)); 
    basket.push(ObjectSchema.find({}, 'sourceId')); 
    return Promise.all(basket); 
}).then(basketDoc => { 
    let mongoObjects = {}, extObjects = {}; 
    basketDoc.pop().forEach(o => mongoObjects[o.sourceId] = o._id); // Mongo retuns array of {_id, sourceId } objects 
    basketDoc.forEach(o => { // ExtSystem returns array of {id, name} objects 
     extObjects[o.id] = { 
      sourceId: o.id, 
      name: o.name 
     } 
    }); 

    let esSet = new Set(Object.keys(extObjects)); 
    let mongoDeleteIds = Object.keys(mongoObjects).filter(oId => !esSet.has(oId)); // Set.has is faster than Array.indexOf 

    let syncPromises = []; 
    syncPromises.push(...Object.keys(extObjects).map(oId => ObjectSchema.findOneAndUpdate({ sourceId: extObjects[oId].sourceId }, extObjects[oId], { upsert: true, new: true }))); 
    syncPromises.push(...mongoDeleteIds.map(oId => ObjectSchema.remove({_id: oId}))); 
    return Promise.all(syncPromises); 
}).then(_ => { 
    return ObjectSchema.find(); 
}).then(doc => { 
    return someBusinessLogic(doc); 
}).catch(errHandler); 
関連する問題