4

非同期並列リクエストに続いてビューを部分的にレンダリングする適切な方法は何ですか?

現在、私は次のことを行っています

// an example using an object instead of an array
async.parallel({
    one: function(callback){
        setTimeout(function(){
            callback(null, 1);
            // can I partially merge the results and render here?
        }, 200);
    },
    two: function(callback){
        setTimeout(function(){
            callback(null, 2);
            // can I partially merge the results and render here?
        }, 100);
    }
},
function(err, results) {
    // results is now equals to: {one: 1, two: 2}
    // merge the results and render a view
    res.render('mypage.ejs', { title: 'Results'});

});

基本的には正常に動作していfunction1, function2, ..., functionNますが、ビューがあれば、最も遅い関数が完了したときにのみレンダリングされます。

ユーザーの遅延を最小限に抑えるために、最初の関数が返されたらすぐにビューをレンダリングし、関数の結果が利用可能になり次第追加できる適切な方法を見つけたいと思います。

4

2 に答える 2

5

必要なのは Facebook のビッグパイプです: https://www.facebook.com/note.php?note_id=389414033919。幸いなことに、nodejs ではストリーミングが組み込まれているため、これは簡単です。残念ながら、非同期テンプレートは面倒なので、テンプレート システムはこれが苦手です。ただし、これは、追加の AJAX 要求を行うよりもはるかに優れています。

基本的な考え方は、最初にレイアウトを送信することです:

res.render('layout.ejs', function (err, html) {
  if (err) return next(err)

  res.setHeader('Content-Type', 'text/html; charset=utf-8')
  res.write(html.replace('</body></html>', ''))

  // Ends the response. 
  // `writePartials` should not return anything in the callback!
  writePartials(res.end.bind(res, '</body></html>'))
})

</body></html>ドキュメントが完成していないため、送信できません。次にwritePartials、並列で実行される一連の非同期関数 (パーシャルまたはページレット) になります。

function writePartials(callback) {
  async.parallel([partial1, partial2, partial3], callback)
})

注: 既に応答を作成しているため、ログに記録する以外にエラーに対してできることはあまりありません。

各パーシャルが行うことは、インライン JavaScript をクライアントに送信することです。たとえば、レイアウトに を含めることができ、ページレットは到着時または「コールバックが終了した」ときにを.stream置き換えます。.streaminnerHTML

function partialStream(callback) {
  res.render('stream.partial.ejs', function (err, html) {
    // Don't return the error in the callback
    // You may want to display an error message or something instead
    if (err) {
      console.error(err.stack)
      callback()
      return
    }

    res.write('<script>document.querySelector(".stream").innerHTML = ' + 
      JSON.stringify(html) + ';</script>')
    callback()
  })
})

個人的には、私はそれを新しい要素.stream.placeholderに置き換えています。.streamその理由は、私は基本的に.placeholder, .placeholder ~ * {display: none}、物事がページを飛び回らないようにするためです。ただし、突然 JS がより複雑になるため、これには DIY フロントエンド フレームワークが必要です。

そこで、あなたの応答がストリーミングされます。唯一の要件は、クライアントが Javascript をサポートしていることです。

于 2013-04-29T20:34:20.343 に答える