2009-10-15 2 views
13

비동기식 애플리케이션 (특히 모든 데이터가 JS를 통해 을 획득해야하는 OpenSocial 코드를 다룰 때)을 처리해야 할 때 Javascript에서 많은 스파게티를 작성하고 있음을 알고 있습니다. . 일반적인 패턴은 다음과 같습니다.자바 스크립트에서 스파게티 코드를 피하는 방법

  1. 사용자가 응용 프로그램에 처음 로그인하면 데이터를 가져옵니다.
  2. 자신의 데이터에서 A를 수행합니다 (예 : 서버에 요청을 보내 친구를 사귀십시오).
  3. 이 데이터에서 B를 수행합니다 (예 : 일부 처리를 위해 친구를 서버로 보냄).
  4. 데이터에서 C를 실행합니다 (예 : 서버 응답이 유효한지 확인하여 다른 작업을 수행 할 수 있음).

이 순차 실행 경로 (1 => 2 => 3 => 4)는 비동기식 모드와 잘 맞지 않습니다. 자연의 아약스 그래서 사용자가 오랜 시간 동안 기다리고 끝내고 코드는 모든 단계 이후 엉망으로 바뀝니다 이전 것들에 따라 달라집니다.

코드 예 :

gadgets.util.registerOnLoadHandler(setupUser()) 
... 
function setupUser() { 
    var req = [get data and setup request] 
    req.send(some_url, some_data, function(response) { getFriendsFor(response.user) }); 
} 

function getFriendsFor(user) { 
    var friends = [get friends from user] 
    var req = [setup request] 
    req.send(some_other_url, some_other_data, function(response { validateFriendsResponse(response.friends) }); 
} 

function validateFriendsResponse(friends) { 
    if (friends.valid()) 
    ... 
    loadCanvas(); 
} 

당신은 각 기능은 이전에 따라 볼 수 있고, 더 나쁜 것, 그것은 도움이 될 수있는 특정 순서 호출해야합니다. 사용자가 기다리는 동안 화면 및 다른 특수 효과를 표시/숨기기와 같은 항목을 추가해야 할 때 상황이 악화됩니다.

어떻게 수정 하시겠습니까?

+6

알 요리가 될 때까지 요리하십시오. –

+2

주된 걱정은 사용자가이 모든 작업을 완료하기 위해 오랜 시간 동안 기다리는 것 같습니다.각 요청이 반환 된 후 사용자에게 어떤 피드백을 보내어 왜 어떤 일이 일어나고 있는지 알 수 있습니다. 3 단계 진행률 표시 줄이나 사용자에게 무슨 일이 일어나는지 알려주는 메시지처럼 간단 할 수 있습니다. (당신은 심지어 aeal에 대한 "망상 스플라인 (reticulating splines)"메시지를 던질 수 있습니다.) –

+0

Sam : 팔을 치고있는 귀여운 로봇으로 화면을로드 중입니다.하지만 코드는 나도 걱정합니다. 두 달 후에 그것을 읽는 데 문제가 있습니다. –

답변

4

하나의 옵션은 현재 상태를 나타내는 변수를 가지며 항상 "AJAX 콜백 함수"인 "컨트롤러"기능을 가질 수 있습니다. 현재 상태에 따라 제어기 기능은 다음 기능을 한 라인에서 호출합니다. 컨트롤러 함수를 단순화하기 위해, 아마도 Javascript 객체를 호출하기 위해 함수의 시퀀스를 저장하기 때문에 컨트롤러 함수가 수행하는 모든 작업은 시퀀스의 다음 함수를 검색하고 패스하는 것입니다. 이 접근법은 항상 함수의 매개 변수입니다 (이전 AJAX 호출에 의해 반환 된 모든 데이터를 포함하는 하나의 자바 스크립트 객체를함으로써 촉진 될 수

예 :.

var user = {}; 
var currentState = 1; 

var someFunction = function(user) {//stuff here that adds data to user via AJAX, advances currentState, and calls controllerFunction as callback}; 
var someOtherFunction = function(user) {//stuff here that does other things to user, advances currentState, and calls controllerFunction as callback} 

var functionSequence = {1:someFunction, 2:someOtherFunction} 

var controllerFunction = function() { 
    //retrieve function from functionSequence based on current state, and call it with user as parameter 
} 
1

자바 스크립트를 구축 MVC 아키텍처

+1

javascriptMVC - 그들은 IE8에서 작동하는 링크를 가져와야한다고 생각합니다! – ScottE

+1

Backbone (http://documentcloud.github.com/backbone/) 및 Spine (http://spinejs.com/)을 경량 클라이언트 측 MVC 프레임 워크로 추가합니다. – jbandi

1

표시, 숨기기 및 상태 기능을 처리하는 코드를 함수로 추출해야합니다. 그런 다음 "스파게티"를 피하기 위해 한 가지 해결책은 익명의 함수를 인라인으로 사용하는 것입니다.

function setupUser() { 
    var req = [get data and setup request] 
    req.send(some_url, some_data, function(response) { 
    var friends = [get friends from user] 
    var req = [setup request] 
    req.send(some_other_url, some_other_data, function(response {   
     if (friends.valid()) 
     ... 
     loadCanvas(); 
    }); 
    }); 
} 
+0

이것은 처음에 내가 한 일이지만, 슬프게도 OpenSocial JS API는 너무 장황하다. OS의 예제 2 ~ 4 줄은 http://gist.github.com/211062에서 확인할 수 있습니다. 일부 코드는 함수에서 추상화 될 수 있지만 여전히 미친 사람처럼 뛰어 다니는 것과 동일한 문제가 있습니다. –

0

당신은 당신의 기능을 독립적으로 운영 할 수 대신 줄에 "다음"함수 호출의 일반적인 콜백과 비동기 사람을 갖출 수 있도록합니다. 그런 다음 JacobM이 말한대로 순서대로 호출 할 "컨트롤러"를 설정하십시오. 나는 (조심이 테스트되지 않았습니다) 보여주기 위해 아래 예제 코드를 수정했습니다

gadgets.util.registerOnLoadHandler(userSetupController()) 
... 
function setupUser(callback) { 
    var req = [get data and setup request] 
    req.send(some_url, some_data, function(response) { callback(response.user) }); 
} 

function getFriendsFor(user,callback) { 
    var friends = [get friends from user] 
    var req = [setup request] 
    req.send(some_other_url, some_other_data, function(response { callback(response.friends) }); 
} 

function validateFriendsResponse(friends) { 
    if (friends.valid()) 
    return true; 
    else 
    return false; 
} 

function userSetupController() { 
    setupUser(function(user){ 
     getFriendsFor(user,function(friends){ 
      if (validateFriendsResponse(friends)) { 
       loadCanvas(); 
      } else { 
       // don't load the canvas? 
      } 
     }); 
    }); 
} 

만들기 콜백은 당신이 그들에 익숙하지 않은 경우 조금 까다로운 - 여기 괜찮은 설명입니다 : http://pixelpushing.net/2009/04/anonymous-function-callbacks/. (JacobM이 제안한 것처럼) 좀 더 복잡해지기를 원한다면 자동으로 처리하는 코드를 작성할 수 있습니다. 함수의 목록을주고 콜백 데이터를 전달하여 순서대로 실행합니다. 편리하지만, 당신의 필요에 과잉 될 수 있습니다.

2

Observer pattern과 같은 종류의 스파게티를 제어 할 수 있습니다. 일부 JavaScript 프레임 워크에는 즉시 사용 가능한 구현 기능이 있습니다 (예 : Dojo's publish/subscribe 기능).

1

일부 문제는 서버에 대한 3 회의 왕복이 필요한 4 단계 프로세스로 생각할 수 있다는 것입니다. 이것이 실제로 하나의 워크 플로우라고 생각하고 사용자가 할 일이 가장 많으면 가장 빠른 속도 향상은 가능한 한 첫 번째 상호 작용에서 많은 정보를 수집하여 왕복 횟수를 줄이는 것입니다. 여기에는 사용자가이 경로를 따르기를 원한다는 상자를 체크하여 단계 사이에 사용자에게 돌아갈 필요가 없도록하거나, 친구 이름을 추측 할 수 있도록 친구들의 이름을 추측 할 수 있도록 허용하는 것도 포함됩니다 처음으로 이름 목록을 미리로드하거나 미리로드합니다.

코드가 사용자가 따라야 할 경로 중 하나 일 경우 코드의 윤곽을 그렸습니다. 각각의 상호 작용에서 사용자가 원하는 것을 찾아 내고 다른 대답이 당신을 다른 방향으로 보냈기 때문에 다중 왕복 이동이 필요합니다. 이것은 당신이 비난하고있는 느슨하게 결합 된 코드 스타일이 실제로 빛나는 때입니다. 사용자 조치로 인해 활동이 진행 중이므로 이전 단계와 각 단계가 연결 해제 된 것처럼 보입니다.

그래서 진짜 질문은 사용자가 코드 작성 방향을 결정하는 시작 부분에 선택 사항이 있는지 여부입니다. 그렇지 않다면 상호 작용이 진행될 것이라는 것을 (또는 강하게 예측하는) 경로를 최적화하고 싶습니다. 반면에 사용자 상호 작용이 프로세스를 주도하게되면 단계를 분리하고 각 상호 작용에 반응하는 것이 옳은 일이지만 더 많은 가능성을 기대할 수 있습니다.

관련 문제