3

私はこの問題が発生したのは初めてではありませんが、私はいつも解決策を見つけることができました。これはうまくいきますが、改善する方法を理解したかったのです。だから、私の例では、私はコースのリストを持っている、と私はそれらのそれぞれの平均採点を計算する必要があります。JavaScript約束事がすでに使用されている場合、JavaScriptの非同期性を克服するにはどうすればよいですか?

var vm = this; 

course.averageRating = vm.getAverageRating(course.id); 

、動作しません何:

明らか
vm.getAverageRating = function (courseId) { 
     let sum = 0, courses = []; 
     courseContext.getUserCourseFeedback(courseId).then(function(results){ 
      courses = results; 
     }); 

     courses.forEach(function (course) { 
      if(course && course.feedback_rating) { 
       sum += course.feedback_rating; 
      } 
     }); 
     return courses.length > 0 ? sum/courses.length : null; 
}; 

、何が起こりますかアプリケーションが実際にサーバーからuserCoursesのリストをダウンロードする前に、courses.forEachが呼び出され、関数は常にnullを返します。次のように

私の回避策は次のとおりです。

vm.averageRatings = {}; 

vm.getAverageRating = function (courseId) { 
    let sum = 0, courses = []; 
    courseContext.getUserCourseFeedback(courseId).then(function(results){ 
     courses = results; 

     courses.forEach(function (course) { 
      if(course && course.feedback_rating) { 
       sum += course.feedback_rating; 
      } 
     }); 

     vm.averageRatings[courseId] = courses.length > 0 ? sum/courses.length : null; 
    }); 
}; 

私はこれが、この問題について移動する最良の方法はないと考えています。最初の例では、それにはの返信文を使用することはできません。また、約束を約束することはできません。あなたが私の場所にいるなら、この問題をどうやって解決しますか?

+3

"私は約束を約束することはできません" ...?さて、あなたは*できました。しかし、あなたは本当にあなたがすでに持っている約束を「返す」必要があります。 – deceze

+0

あなたが思いついた "回避策"は実際に(正しい)方法であると思います。最もエレガントではないが、正しい。 –

+0

同じ問題です、私はもっときれいなコード結果を得たい –

答えて

1

結構ですが、あなたは

  • リターンの代わりに、いくつかの事前に決めオブジェクト
  • に書き込むの値のための約束はあなたのコードは、具体的に変数宣言を簡素化すべきである

function getAverageRating(courseId) { 
    return courseContext.getUserCourseFeedback(courseId).then(function(courses) { 
//^^^^^^            ^^^^^^^ 
    let sum = 0; 
    for (const course of courses) 
     sum += course && course.feedback_rating || 0; 
    return courses.length > 0 ? sum/courses.length : null; 
    }); 
}; 

getAverageRating(course.id).then(avg => { 
    course.averageRating = avg; 
}); 
+0

ありがとう!それが最善の解決策です。 return courseContext.getUserCourseFeedback ....は数値の代わりにオブジェクトを返します(平均値を得るにはd。$$ state.valueのようなものです)。オブジェクト内のいくつかのレイヤーに値を渡すだけでなく、それを修正する方法があるかどうかは分かりますか? –

+0

約束を返します。約束は '.then()'を使用して待たなければなりません。その私有財産を覗かないでください。 – Bergi

+0

オハイオ州のええ、私の悪い、ありがとう! –

1

getAverageRating は、非同期です。このような

var cache = {}; 
vm.getAverageRating = function (courseId) { 

    return cache[courseId] || 
    (cache[courseId] = courseContext.getUserCourseFeedback(courseId) 
    .then(function(courses){ 
     return (
     courses.reduce((sum,course)=>sum + (course.feedback_rating || 0),0) 
     /courses.length) || null; 
    }) 
);  
}; 

使用可能:

vm.getAverageRating(1).then(res => console.log(res)); 
vm.getAverageRating(1).then(res => console.log(res)); 

の両方が同じ約束を指しますので、彼らは同じ結果と同時に解決されます、あなたはしたい結果をキャッシュするが。要求は2つではなく、1つだけです。

0

バーベルまたはノード8.xを使用している場合は、async/awaitを使用できます。

これは、このような何かにあなたの機能を簡素化します:

vm.getAverageRating = async function (courseId) { 
     let sum = 0, courses = []; 
     await courseContext.getUserCourseFeedback(courseId).then(function(results){ 
      courses = results; 
     }); 

     courses.forEach(function (course) { 
      if(course && course.feedback_rating) { 
       sum += course.feedback_rating; 
      } 
     }); 
     return courses.length > 0 ? sum/courses.length : null; 
}; 
+1

いいえ、あなたは間違ったものを待っています.. –

+0

それは本当に単純化ではありません。 – Bergi

0

vm.getAverageRating()が故に、それは同期タイムラインに何も返さないことができ、非同期操作の結果に依存しています。あなたがしていることは、基本的に正しいですが、代わりにvm.getAverageRating()が約束を返す方が良いでしょう。だから私はあなたのコードを次のように模倣するだろう。

function getAverageRating(n){ 
 
    return Promise.resolve(Array.from({length: n}) 
 
           .map(_ => 25+Math.floor(76*Math.random()))) // get course ratings 
 
       .then(function(crs){ 
 
         var sum = crs.reduce((p,c) => p+c), 
 
          avg = crs.length ? sum/crs.length : null; 
 
         return [crs,avg]; 
 
         }); 
 
} 
 
getAverageRating(10).then(([crs,avg]) => console.log("course ratings are: ", crs, "average is: ", avg));

1

質問

あなたは私の場所にあった場合はどのようにこの問題を解決するに答えるために?ES2015 +が

不慣れである場合に、コードの最初のブロックは、単にある

vm.getAverageRating("someID").then(result => { 
    // result is the result you want 
}); 

:あなたの2つのアプローチの組み合わせがどのように使用する

vm.getAverageRating = function (courseId) { 
return courseContext.getUserCourseFeedback(courseId).then(courses => courses.length > 0 ? (courses.map(course => (course && course.feedback_rating) ? course.feedback_rating : 0).reduce((a, b) => a + b))/courses.length : null); 
}; 

あろう

vm.getAverageRating = function (courseId) { 
    return courseContext.getUserCourseFeedback(courseId).then(function (courses) { 
     return courses.length > 0 ? courses.map(function (course) { 
      return (course && course.feedback_rating) ? course.feedback_rating : 0; 
     }).reduce(function (a, b) { 
      return a + b; 
     })/courses.length : null; 
    }); 
}; 
約束を使うは
+0

oops、ええ、元々コードを詰めました:p –

+0

返品がありません:/ –

+0

はい。私はそれを追加したと思った。どちらが私のコメントの理由だった –

関連する問題