복붙노트

[REDIS] 노드 / 레디 스 및 콜백와 제어 흐름 문제?

REDIS

노드 / 레디 스 및 콜백와 제어 흐름 문제?

나는 노드와 레디 스와 제어 흐름 문제에 대한 몇 가지 조언을 요청할 수 있습니다하세요? (파이썬 코더 노력 일명는 자바 스크립트를 사용하세요)

client.smembers 및 client.get (레디 스 조회) 필요가 단순히 문을 것보다 콜백 할 이유를 나는 이해하지 않는다 - 그것은 매우 복잡 생활을한다.

기본적으로 나는 세트를 조회하고 싶습니다, 나는 세트에 대한 결과가있을 때 다음, 나는 각 결과에 대한 GET을 수행해야합니다. 나는 모든 데이터를 가지고 때, 나는 다시 클라이언트로 방송 할 필요가있다.

현재 내가 더러워 보인다 전역 객체를 사용하여, 두 개의 콜백 내에서이 작업을 수행. 심지어 확인이 안전 경우 아니에요 (가 완료 한 client.get의 코드 대기 서로를 시작하기 전에?).

현재 코드는 다음과 같습니다 :

var all_users = [];
// Get all the users for this page.
client.smembers("page:" + current_page_id, function (err, user_ids ) {
  // Now get the name of each of those users.
  for (var i = 0; i < user_ids.length; i++) {
     client.get('user:' + user_ids[i] + ':name', function(err, name) {
       var myobj = {};
       myobj[user_ids[i]] = name;
       all_users.push(myobj);  
       // Broadcast when we have got to the end of the loop, 
       // so all users have been added to the list - 
       // is this the best way? It seems messy.  
       if (i === (user_ids.length - 1)) {
           socket.broadcast('all_users', all_users); 
       }
     });       
   }
 });

그러나 이것은 매우 지저분한 것 같다. 그것은이 작업을 수행하는 가장 좋은 방법은 정말? 하려면 어떻게해야 모든 조회가 socket.broadcast를 호출하기 전에 수행 한 것을 할 수 있는가?

긁힌 자국은 어떤 조언에 미리 감사드립니다 머리.

해결법

  1. ==============================

    1.즉 노드가 무엇인지입니다. (필자는 확신이 항목은 더 여기 충분한 시간보다 논의되었다 해요, 다른 질문을 통해 보면, 거기 확실히이다)

    즉 노드가 무엇인지입니다. (필자는 확신이 항목은 더 여기 충분한 시간보다 논의되었다 해요, 다른 질문을 통해 보면, 거기 확실히이다)

    즉 콜백 함수에 대한 ERR을 무엇이다. 이것은 좀 노드의 표준 - 콜백의 첫 번째 매개 변수는 오류 개체 (null의 모든 것을 잘 경우)입니다. 그러니 그냥 확인하기 위해이 같은 것을 사용 오류없이 발생

    if (err) {
      ...    // handle errors.
      return // or not, it depends.
    }
    
    ... // process results
    

    당신은 그것에 익숙해 있습니다. 사실은 코드가 잘 포맷 및 프로젝트가 교묘하게 구성 될 때, 그것은 좋은 찾는거야.

    다른 방법은 다음과 같습니다 :

  2. ==============================

    2.당신이 완전히 물건 콜백 스타일을 쓰기 싫어하는 경우에, 당신은 streamlinejs을 시도 할 수 있습니다 :

    당신이 완전히 물건 콜백 스타일을 쓰기 싫어하는 경우에, 당신은 streamlinejs을 시도 할 수 있습니다 :

    var all_users = [];
    // Get all the users for this page.
    var user_ids = client.smembers("page:" + current_page_id, _);
    // Now get the name of each of those users.
    for (var i = 0; i < user_ids.length; i++) {
      var name = client.get('user:' + user_ids[i] + ':name', _);
      var myobj = {};
      myobj[user_ids[i]] = name;
      all_users.push(myobj);  
    }
    socket.broadcast('all_users', all_users);
    

    참고이 변형의 단점은 하나의 사용자 이름이 한 번에 인출 될 것입니다. 또한, 당신은 여전히이 코드는 정말 무엇을 알고 있어야합니다.

  3. ==============================

    3.비동기은 훌륭한 라이브러리입니다 당신은 살펴 보셔야합니다. 왜 ? 클린 코드 / 공정 / 추적이 용이 등등

    비동기은 훌륭한 라이브러리입니다 당신은 살펴 보셔야합니다. 왜 ? 클린 코드 / 공정 / 추적이 용이 등등

    또한, 모든 비동기 함수는 루프에 대한 후 처리되는 것을 명심하십시오. 당신이 exemple, 그것은 잘못 "내가"값이 발생할 수 있습니다. 사용 폐쇄 :

     for (var i = 0; i < user_ids.length; i++) { (function(i) {
     client.get('user:' + user_ids[i] + ':name', function(err, name) {
       var myobj = {};
       myobj[user_ids[i]] = name;
       all_users.push(myobj);  
       // Broadcast when we have got to the end of the loop, 
       // so all users have been added to the list - 
       // is this the best way? It seems messy.  
       if (i === (user_ids.length - 1)) {
           socket.broadcast('all_users', all_users); 
       }
     });       
    })(i)}
    

    그것의 마무리는 비동기 같은 재귀 패턴을 사용할 때 무엇을 알고 당신이해야 (내가 생각하는) 않습니다. 그것의 많은 간단한은 스스로를하고.

    async.series({
      getMembers: function(callback) {
         client.smembers("page:" + current_page_id, callback);
      }
    }, function(err, results) {
       var all_users = [];
       async.forEachSeries(results.getMembers, function(item, cb) {
        all_users.push(item);
        cb();
       }, function(err) {
          socket.broadcast('all_users', all_users); 
       });
    });
    

    이 코드는 유효하지 않을 수 있습니다,하지만 당신은 그것을 할 방법을 알아낼 수 있어야합니다.

    단계 라이브러리가 좋은도 (만 30 ~ 코드의 라인 내 생각)

  4. ==============================

    4.모두가 콜백 지옥 동의 그래서 오른쪽, 더 부에노는 없다. 이 글을 쓰는 현재, 콜백은 노드의 죽어가는 기능입니다. 불행하게도, 레디 스 라이브러리는 약속을 반환에 대한 네이티브 지원이 없습니다.

    모두가 콜백 지옥 동의 그래서 오른쪽, 더 부에노는 없다. 이 글을 쓰는 현재, 콜백은 노드의 죽어가는 기능입니다. 불행하게도, 레디 스 라이브러리는 약속을 반환에 대한 네이티브 지원이 없습니다.

    그러나 당신이 그렇게 등에서 필요로 할 수있는 모듈이있다 :

    유용한 =은 ( "좋은")을 필요로 CONST;

    이 노드 런타임에 포함되어 있으며 우리가 사용할 수있는 유틸리티 함수, "promisify"인 그들 중 하나의 무리가되는 표준 라이브러리입니다 : https://nodejs.org/api/util.html#util_util_promisify_original

    우리가 지금 업데이트 된 대답이 질문을 업데이트 할 수 있도록이, -v 8.0.0의 출시와 함께 추가되면서 지금은 물론 당신이 7 년 전에이 질문을 할 때, util.promisify (원본)은 존재하지 않았다.

    그래서 promisify 함수이며, 우리는 client.get처럼 그것을 함수를 전달할 수 있습니다 ()하고 불쾌한 콜백 동작을 새로운 기능을 반환하고 대신이 약속을 반환하기 위해 좋은 깔끔한 그것을 감싼다.

    그래서 promisify 마지막 인수로 콜백을 허용하고 대신 약속을 반환 할 수있는 기능을 소요하고 당신이 7 년 전 원 우리는 오늘날 여유 있다는 정확한 동작 이잖아처럼 들린다.

    const util = require("util");
    client.get = util.promisify(client.get);
    

    우리가 util.promisify하기 위해 갔지 () 함수에 대한 참조를 전달하는 그래서 ().

    이것은 대신 약속을 반환 콜백을 구현하는 그래서 대신에 그것을 감싸고, 당신의 기능을합니다. util.promisify () 그래서 promisified 된 새로운 기능을 반환합니다.

    당신이 새로운 기능을 가지고 client.get에 기존의 것을 대체 할 수 있도록 (). 요즘, 당신은 레디 스 조회를위한 콜백을 사용할 필요가 없습니다. 그래서 지금 당신은 비동기 / await를 구문 같은 사용할 수 있습니다 :

    CONST cachedMembers AWAIT client.get = ( '사용자'+ user_ids [I]);

    우리가 해결해야 할이 대기하고 어떤 그래서 그것은 cachedMembers에 할당됩니다으로 해결합니다.

    이 코드는 더욱 더 ES6 배열 도우미 방법을 사용하는 대신 루프에 대한 업데이트 할 정리 될 수있다. 나는 그렇지 않으면 영업 이익은 무용지물이었다,이 대답은 현재 사용자에게 유용합니다 바랍니다.

  5. from https://stackoverflow.com/questions/7971945/control-flow-issue-with-node-redis-and-callbacks by cc-by-sa and MIT license