98..Etc/jQuery2014. 4. 1. 16:47
반응형

출처 : http://findfun.tistory.com/m/post/382


jQuery.ajax()

원문 링크  http://api.jquery.com/jQuery.ajax/

권고사항 : 아래 글을 보시기 전에 권고드립니다. 아래는 발번역과 오역 그리고 미처 다 한글화가 되어있지 않습니다. 의미도 모른채 번역된 부분이 많기 때문에 다 건너띠고 아래쪽 예제만 보시길 강력히 권고 드립니다. 나빠진 정신건강에 대해 책임(?)지지 않습니다. ^^;;;;

jQuery.ajax( url [, settings] )Returns : jqXHR

개요 : 비동기 HTTP (Ajax) 요청을 수행합니다.

  • jQuery.ajax( url [, settings] )
  • url 요청을 보낼 URL 문자열
  • settings key/value 쌍으로 구성된 Ajax 요청 설정값. 모든 값들은 생략이 가능한 옵션값 임. 기본적인 설정값을 $.ajaxSetup() 에 정의할 수 있음. 모든 세팅에 대한 내용이 궁금하시면 jQuery.ajax( settings ) 을 참고하세요.
  • jQuery.ajax( settings )
  • settings key/value 쌍으로 구성된 Ajax 요청 설정값. 모든 값들은 생략이 가능한 옵션값 임. 기본적인 설정값을 $.ajaxSetup() 에 정의할 수 있음.
  • acceptsMap
    Default: 데이터 타입에 의존적 depends on DataType

    content 타입을 헤더에 포함하여 서버에 보내면 응답 시 같은 타입으로 리턴이 됩니다. 만약 accepts 세팅값을 수정하려 한다면 $.ajaxSetup() 함수에서 해야 합니다.

    asyncBoolean
    Default: true

    기본으로 사용하면, 모든 요청은 비동기방식으로 동작합니다. 만일 동기방식으로 사용하려면 이 값을 false로 세팅하세요. 크로스도메인(2개의 도메인 사이의 정보교환)과 dataType: "jsonp" 인 경우는 동기방식이 지원되지 않습니다. 동기방식은 요청이 처리될 때까지 브라우져가 일시적인 잠금상태가 됩니다.

    beforeSend(jqXHR, settings)Function

    요청 전 콜백함수이며, 이 함수에서 요청을 보내기 전 jqXHR 객체를 수정할 수 있습니다. 이 함수에서 false를 반환하면 Ajax 요청이 취소됩니다.jQuery 1.5부터 beforeSend 옵션은 요청의 type에 상관없이 호출할 수 있습니다.

    cacheBoolean
    Default: true, dataType 이 'script' 와 'jsonp' 일때는 false로 세팅

    만일 이 값을 false로 하면, 브라우저의 캐쉬사용을 강제적으로 막습니다. 또한 false 세팅하면 URL 쿼리 스트링에 "_=[TIMESTAMP]" 값이 추가됩니다.

    complete(jqXHR, textStatus)Function, Array

    요청이 완료되었을 때 호출되는 함수입니다. 요청에 대한 응답이 success 나 error 가 반환된 후 실행됩니다. 이 함수는 2개의 인자를 갖습니다. jqXHR 객체와 요청에 대한 상태값("success""notmodified""error""timeout""abort""parsererror")으로 구성되어 있습니다. 더 자세한 내용은Ajax Event를 참고하십시오.

    contents(added 1.5)Map

    문자열과 정규표현식이 쌍으로 이루어진 맵 데이터 입니다. jQuery는 응답 데이터를 이 맵 데이터를 기준으로 파싱합니다.

    contentTypeString
    Default: 'application/x-www-form-urlencoded'

    서버에 데이터를 보낼 때 사용되는 content-type 입니다. 기본값은 "application/x-www-form-urlencoded" 입니다. 명시적으로 바꾸려면 $.ajax() 함수안에서 content-type을 세팅해 줘야 합니다. 서버로 데이터를 보낼 때는 언제나 UTF-8 charset를 사용합니다. 따라서 서버 사이드 프로그램 시 그에 맞게 디코딩을 하여 사용해야 합니다.

    contextObject

    This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax). For example, specifying a DOM element as the context will make that the context for the complete callback of a request, like so:

    $.ajax({
    	  url: "test.html",
    	  context: document.body
    	}).done(function() { 
    	  $(this).addClass("done");
    	});

    converters(added 1.5)Map
    Default: {"* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML}

    데이터 타입을 변환합니다.

    crossDomain(added 1.5)Boolean
    Default: false : 같은 도메인 내의 요청일 경우, true : 크로스 도메인 간의 요청일 경우

    만일 2개의 다른 도메인(CrossDomain)간의 데이터 교환이라면(JSONP와 같은), 이 세팅값을 true로 해야 합니다.

    dataObject, String

    서버로 보낼 데이터입니다. GET 요청 형태의 query 스트링으로 변환되어 보내집니다. GET 요청 파라미터에 자동으로 추가됩니다. 이런 자동 추가를 방지하기 원하면 processData 옵션을 보시기 바랍니다. 이 객체는 key/value의 쌍으로 이루어져 있습니다. 만일 value가 배열이라면, jQuery는 같은 key로 여러 value를 직렬화 구성을 하게 됩니다. 아래쪽에 추가적인 설명이 있습니다.

    dataFilter(data, type)Function

    이 함수는 응답 원시 데이터를 핸들링 할 수 있습니다. 정제된 데이터를 반활해야 할 필요가 있을 때 사용합니다. 두개의 인자가 있는데 data 와 그 데이터의 type입니다.

    dataTypeString
    Default: Intelligent Guess (xml, json, script, or html)

    서버에서 응답 받을 때는 데이터의 타입을 jQuery가 추정하여 처리합니다. 만일 인자를 아무것도 적지 않으면 응답 메시지의 MIME type을 기초로하여 처리하게 되는 것입니다. MIME type이 XML 이며 yield XML을 생성하고, 1.4 JSON은 JavaScript 객체를 생성, 1.4 script라면 script를 실행하고, 그 외 다른 것들은 문자열을 리턴합니다.

    • "xml": jQuery가 XML 문서를 반환합니다.
    • "html": 평문 HTML 을 반환합니다.
    • "script": JavaScript를 실행하고 평문 텍스트를 리턴합니다. 쿼리 스트링에 "_=[TIMESTAMP]" 를 추가하면 캐싱을 방지할 수 있습니다. 이런 방식은cache 옵션을 true로 바꾸는 역할을 합니다.
    • "json": JSON을 JavaScript 객체형태로 반환합니다. jQuery 1.4에서 JSON 데이터는 엄격한 방식으로 파싱되었습니다. 형식에 맞지않는 JSON 데이터는 요청이 거부되고 error을 발생시켰습니다. JSON 포맷에 대해 궁금하시면 json.org 을 방문해 보세요.
    • "jsonp": JSONP 를 사용하여 JSON 블럭을 로드합니다. 쿼리 스트링에 "_=[TIMESTAMP]" 를 추가하면 캐싱을 방지할 수 있습니다. 이런 방식은 cache옵션을 true로 바꾸는 역할을 합니다.
    • "text": 평문 텍스트 문자열을 반환합니다.
    • multiple, 공백 구분 값(space-separated values): jQuery 1.5에서, dataType을 변환할 수 있게 되었습니다. 예를들어 응답받은 text 를 XML 로 변화하고 싶으면, "text xml"이라고 사용하면 됩니다.

    error(jqXHR, textStatus, errorThrown)Function

    요청(request)이 실패하면 호출됩니다. 이 함수는 3개의 인자를 통해 데이터를 받을 수 있습니다. jqXHR 객체는 발생한 에러 타입과 추가적인 예외 사항을 담고 있습니다. 두번째 인자에는 "timeout""error""abort""parsererror" 와 같은 상황을 담고 있습니다. 세번째 인자에는 HTTP 에러가 담겨 있는데, "Not Found" 나 "Internal Server Error." 같은 것 들입니다. Note: cross-domain 스크립트나 JSONP 요청에 대해서는 이 함수를 사용할 수 없습니다.

    globalBoolean
    Default: true

    전역 Ajax 이벤트 핸들러를 제어합니다. 기본값은 true 입니다. 이 값을 false로 하면 ajaxStart 나 ajaxStop 같은 전역 핸들러의 실행을 막을 수 있습니다.

    headers(added 1.5)Map
    Default: {}

    요청 시 추가로 보낼 헤더 정보입니다. key/value 쌍으로 구성됩니다. 이 세팅값은 beforeSend 함수가 호출되기 전에 처리되야 합니다. beforeSend 함수 내에서 value 값을 재조정 할 수 있습니다.

    ifModifiedBoolean
    Default: false

    마지막 request 이후 response가 변경되었을 경우에만 request가 성공하도록 허용하는 값입니다. 이것은 마지막 수정 정보를 헤더에서 체크하는 것입니다. 기본값은 false 이며 이 옵션이 무시됩니다. 즉, 언제나 request에 대한 응답을 체크하는 것입니다. jQuery 1.4 부터는 수정되지 않은 데이터를 알아내기 위한 'etag' 를 체크할 수 있습니다.

    isLocal(added 1.5.1)Boolean
    Default: 현재 프로토콜을 유지 depends on current location protocol

    jQuery에서 인식하지 못하더라도 현재 환경이 "local(예, filesystem)" 로 인식할 수 있도록 허용합니다.(이건 무슨 의미인지 모르겠네요.) 다음 file*-extensionwidget 프로토콜 들은 현재 local로 인식합니다. 만일 isLocal 세팅을 변경을 원하시면 $.ajaxSetup() 함수에서 하실 것을 권장드립니다.

    jsonpString

    jsonp 요청에 사용한 콜백 함수명을 오버라이드 합니다. 이 값은 url에 포함된 쿼리 스트링의 부분인 'callback=?' 문자열 중 'callback' 을 대신하여 사용됩니다. 예를 들면 {jsonp:'onJSONPLoad'} 라고 세팅하면 서버에 'onJSONPLoad=?' 처럼 전달되게 되는 것입니다. jQuery 1.5 부터는 jsonp 옵션을false 로 세팅하여 URL에 "?callback" 이 추가되는 것을 방지하거나 "=?" 을 변조되는 시도를 방지할 수 있습니다. 이러한 경우 명시적으로jsonpCallback 세팅값을 이용하여야 합니다. 예를 들어, { jsonp: false, jsonpCallback: "callbackName" } 와 같이 사용합니다.

    jsonpCallbackString, Function

    JSONP 요청 시 콜백 함수명을 지정합니다. 지정하지 않으면 jQuery에서 임의적으로 부여하게 됩니다. 요청(request)에 대해 쉽게 핸들링 할 수 있도록 유니크한 이름이 부여됩니다. 콜백 이름을 당신이 지정할 수도 있습니다. jQuery 1.5부터 함수명을 세팅할 수 있게 되어습니다.

    mimeType(added 1.5.1)String

    XHR의 마임 타입을 설정합니다.

    passwordString

    HTTP 엑세스 시 패스워드를 설정합니다.

    processDataBoolean
    Default: true

    By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false.

    scriptCharsetString

    Only for requests with "jsonp" or "script" dataType and "GET" type. Forces the request to be interpreted as a certain charset. Only needed for charset differences between the remote and local content.

    statusCode(added 1.5)Map
    Default: {}

    요청에 대한 응답 시 전달된 HTTP 상태 코드와 실행될 함수로 이루어진 집합입니다. 예를 들어, 404 상태에 대해 알림창을 보여주는 경우는 아래 예와 같습니다.

    $.ajax({
    	  statusCode: {
    		404: function() {
    		  alert("page not found");
    		}
    	  }
    	});

    만일 요청이 성공했다면, 상태코드는 성공 콜백함수로 같은 파라미터를 전달합니다. 반대로 error 가 발생해도 같은 파라미터를 error 콜백 함수로 전달하게 됩니다.

    success(data, textStatus, jqXHR)Function, Array

    요청이 성공했을 때 호출됩니다. 이 함수는 3개의 인자를 전달합니다. data 인자는 서버에서 전달된 데이터를, 두번째는 데이터의 타입을, 마지막으로 jqXHR(jquery 가 변형한 XMLHttpRequest 객체)를 전달하게 됩니다. jQuery 1.5 부터, success 시 함수 배열을 전달 받을 수 있습니다.

    timeoutNumber

    요청 대기 시간을 세팅합니다.

    traditionalBoolean

    이 세팅값을 true로 하면 전통적인 스타일의 파라미터 직렬화를 사용할 수 있습니다.(이건 뭔가요 ㅡㅡ;;)

    typeString
    Default: 'GET'

    요청 시 POST 와 GET 방식을 결정합니다. 기본값은 GET 방식입니다.

    urlString
    Default: 현재 페이지 The current page

    요청을 보낼 URL 주소입니다.

    usernameString

    HTTP 요청 시 필요한 username 값 입니다.

    xhrFunction
    Default: IE 에서는 ActiveXObject 이고 다른 브라우저는 XMLHttpRequest

    XMLHttpRequest 객체입니다.

    xhrFields(added 1.5.1)Map

    기본 XHR 객체의 키-값의 맵 데이터 입니다. 예를 들어, 크로스 도메인에서 withCredentials 값을 true로 하고 싶다면 아래와 같이 세팅합니다.

    $.ajax({
    	   url: a_cross_domain_url,
    	   xhrFields: {
    		  withCredentials: true
    	   }
    	});

    jQuery 1.5 부터 withCredentials 속성은 네이티브 XHR 에서 전달하지 못합니다.

$.ajax() 함수는 jQuery에서 사용되는 모든 Ajax 의 근간입니다. 종종 이 함수를 직접 호출하지 않아도 쉽게 사용할 수 있는 함수들이 있습니다.$.get() 이나 .load() 같은 함수들이 그것들입니다. 만일 세팅값을 변경할 필요가 있을 경우에도 $.ajax() 함수에서 유연하게 변경할 수 있습니다.

$.ajax();

Note: 기본 세팅값을 전역적으로 관리하려면 $.ajaxSetup() 함수를 이용해야 합니다.

위의 옵션값을 아무것도 없이 사용하면 현재 페이지에서 응답 결과를 제어하지 못합니다. 이게 가능하려면 콜백 함수를 지정해야 합니다.

The jqXHR Object

jQuery XMLHttpRequest (jqXHR) 객체는 $.ajax() 함수에서 반환됩니다. jQuery 1.5 부터 브라우저의 네이티브 XMLHttpRequest 객체의 상위집합 입니다. 예를 들어, 이 객체는 responseText 과 responseXML 속성을 포함하고 있을 뿐만 아니라 getResponseHeader() 함수도 포함하고 있습니다. 전송 메카니즘이 XMLHttpRequest 가 아닌 다른 것일 경우( JSONP 요청에 대한 script 태그 같은) jqXHR 객체는 네이티브 XHR 기능을 이용하게 됩니다.

jQuery 1.5.1부터, jqXHR 객체는 overrideMimeType() 함수를 사용하게 됩니다. (이것은 jQuery 1.4.x 에서는 사용되었지만, jQuery 1.5 에서 일시적으로 삭제되었음). .overrideMimeType() 함수는 method may be used in the beforeSend() 콜백 함수에서 사용될 수 있습니다. 예를 들어, 응답의 content-type header 를 수정하기 위해서 아래와 같이 사용할 수 있습니다.:

$.ajax({
  url: "http://fiddle.jshell.net/favicon.png",
  beforeSend: function ( xhr ) {
    xhr.overrideMimeType("text/plain; charset=x-user-defined");
  }
}).done(function ( data ) {
  if( console && console.log ) {
    console.log("Sample of data:", data.slice(0, 100));
  }
});

$.ajax() 에서 반환된 jqXHR 객체는 jQuery 1.5 의 약속된 인터페이스를 구현하여 모든 속성, 메소드, 동작들을 제공하고 있습니다.(더 많은 정보를 원하시면 Deferred object 를 참고). 편의성과 일관성을 위해 $.ajax() 함수에서 사용될 콜백 함수들로 jqXHR 객체는 .error().success().complete()와 같은 함수들을 사용할 수 있습니다. 이들 함수들은 $.ajax() 요청이 종료되었을 때 호출되고 모두 같은 인자를 전달받게 됩니다. 이것은 단일 요청에서 여러 콜백 함수를 지정할 수도 있고 요청이 완료된 후에도 콜백 함수를 지정할 수 있습니다.

Notice: jqXHR.success()jqXHR.error()jqXHR.complete() 콜백 사용은 1.8 버전부터 사용이 중지됩니다. 이런 사용을 제거하거나 jqXHR.done(),jqXHR.fail()jqXHR.always() 함수들로 대체하십시오.

// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.ajax( "example.php" )
    .done(function() { alert("success"); })
    .fail(function() { alert("error"); })
    .always(function() { alert("complete"); });

// perform other work here ...

// Set another completion function for the request above
jqxhr.always(function() { alert("second complete"); });

For backward compatibility with XMLHttpRequest 이전 버젼과의 호환성을 위해, jqXHR 객체는 아래와 같은 속성과 메소드들을 제공합니다.

  • readyState
  • status
  • statusText
  • responseXML or responseText
  • setRequestHeader(name, value)
  • getAllResponseHeaders()
  • getResponseHeader()
  • abort()

하지만 onreadystatechange 매커니즘은 제공되지 않기 때문에 successerrorcompletestatusCode 이 상황들을 모두 커버 해야할 필요성이 있습니다.

Callback Function Queues

beforeSenderrordataFiltersuccesscomplete 옵션들 모두는 적절한 시간에 호출할 수 있는 콜백 함수를 가질 수 있습니다.

jQuery 1.5부터, error (fail), success (done), complete (always) 콜백 함수들은 큐에서 선입선출(first-in, first-out) 방식으로 제어할 수 있습니다. 이 의미는 콜백 함수마다 처리 로직을 수행할 수 있다는 뜻입니다. Deferred object methods 를 참고하여 $.ajax() 함수에서 콜백 시의 내부처리에 대해 알아볼 수 있습니다.

모든 콜백 함수의 this 키워드는 $.ajax 에서 전달된 context 의 객체들을 가르킵니다. 만일 context 가 지정되지 않았다면 this는 Ajax 세팅 자체를 지칭하게 됩니다.

JSONP 나 cross-domain 의 GET 요청 같은 XHR을 사용하지 않는 Ajax 방식을 사용할 경우에 XMLHttpRequest 나 textStatus 파리미터들은 undefined값을 가지게 됩니다.

아래는 $.ajax()에서 콜백 시 발생하는 훅(hook - I/O 시 정의된 상수값들 정도로 생각하면 됨) 값들 입니다.

  1. beforeSend jqXHR 객체와 파라미터 settings 맵을 받습니다.
  2. error 요청이 실패했을 경우 순서대로 등록됩니다. error 타입 문자열과 exception 객체로 구성된 jqXHR 들을 받습니다. 몇몇 Some 내장 error들은 exception 객체에 "abort", "timeout", "No Transport"와 같은 문자열이 넘어옵니다.
  3. dataFilter 성공적으로 응답이 되었을 경우 즉시 호출됩니다. 반환된 데이터와 dataType 을 받을 수 있고 success 쪽으로 변경된 데이터를 전달해야 합니다.
  4. success 요청이 성공하면 요청된 순서에 따라 호출됩니다. 반환된 데이터와 성공 코드를 포함한 문자열 그리고 jqXHR 객체를 받을 수 있습니다.
  5. complete 요청이 실패하거나 성공에 관계없이 요청이 종료되면 순서에 따라 발생합니다. 성공 또는 실패에 대한 코드를 담은 jqXHR 객체를 받습니다.

예를 들어, HTML 이 반환되고 이것을 사용하고 싶다면 success 핸들러를 사용해야 합니다.

$.ajax({
  url: 'ajax/test.html',
  success: function(data) {
    $('.result').html(data);
    alert('Load was performed.');
  }
});

Data Types

$.ajax() 함수는 검색한 데이터에 대한 정보를 제공하는 서버에 의존합니다. 만일 서버에서 XML 데이터가 제공되었다면, 일반적인 XML 메소드나 jQuery의ㅣ 선택자(selector)들을 사용하여 제어할 수 있습니다. 만일 위의 예제와 같이 HTML 같은 것이라면 데이터를 text 처럼 취급할 수도 있습니다.

별개의 다른 데이터를 dataType 옵션을 이용하여 다룰 수 있습니다. dataType 으로는 xml htmljsonjsonpscripttext.

text 나 xml 타입은 jqXHR 객체의 속성인 responseText 나 responseXML 을 통해 success 핸들러에서 간단하게 받을 수 있습니다.

Note: 웹 서버에서 사용한 MIME 타입과 데이터 요청 시의 dataType 값이 같은지 확인해야 합니다. 특히 XML 은 서버에서 text/xml 또는application/xml 로 반환했는지 확인하고 그에 맞춰 사용해야 합니다.

만일 html 을 지정하는 경우, HTML 이 반환 되기 전에 내부의 JavaScript 는 실행이 된 후 반환이 됩니다. 비슷하게 script 를 정의했다면, 서버에서 반환될 때 인라인 JavaScript 는 실행이 되고 반환되게 됩니다.

json 타입은 The json JavaScript 객체로 가져온 데이터 파일을 분석하고 결과 데이터로 만들어진 객체를 반환합니다. 이렇게 하기 위해서는, 브라우저가 지원한다면 jQuery.parseJSON() 을 사용하거나, 지원하지 않는다면 Function constructor 을 사용해야 합니다. 형식에 맞지 않는(Malformed) JSON 데이터는 에러가 발생하게 되는데 더 많은 정보는 json.org에서 보실 수 있습니다. JSON 데이터는 구조화된 데이터의 이동에 편리합니다. JavaScript 로 처리하기에 간결하고 쉽습니다. 만일 외부 서버에서 가져와야 하는 데이터라면, jsonp 타입을 대신 사용할 수 있습니다.

이 jsonp 타입은 URL 쿼리스트링에 callback=? 이라는 문자열이 추가됩니다. 서버는 유효한 형태의 JSONP 반환 데이터를 콜백(callback) 이름을 사용하여 반환하게 됩니다. $.ajax() 의 옵션인 callback 이외에 다른 파라미터를 지정하여 사용할 수 있습니다.

Note: JSONP 는 확장된 JSON 포맷입니다.

script 나 jsonp 데이터 타입이 사용 가능한 원격 서버에서 데이터를 가져왔을 때, error 콜백과 글로벌 이벤트는 발생하지 않습니다.

Sending Data to the Server

기본적으로, Ajax는 GET HTTP 방식입니다. POST 방식이 필요할 경우, type 옵션값을 이용하면 됩니다. POST 데이터가 서버로 전송될 경우 W3C XMLHTTPRequest 표준인 UTF-8 캐릭터셋을 이용하게 됩니다.

data 옵션값은 key1=value1&key2=value2 형태의 쿼리 스트링을 사용할 수 있습니다. 또한 {key1: 'value1', key2: 'value2'} 형태도 사용이 가능합니다. 만일 후자의 형태를 사용할 경우, 데이터를 보내기 전에 jQuery.param()을 사용하여 데이터를 가공해야 합니다. 이 과정은 processData 을 false로 세팅하면 해결할 수 있습니다. 이 과정을 수행하면 서버로 XML 데이터를 보낼 때 contentType 타입이 application/x-www-form-urlencoded 로 변경되는 것을 방지할 수 있습니다. (음, 이 부부은 사실 명확치 않네요. 좀더 공부가 필요합니다. ㅜㅜ)

Advanced Options

global 옵션으로 .ajaxSend().ajaxError() 그리고 이 함수로 인해 호출되는 함수들의 실행을 제어할 수 있습니다. cross-domain 스크립트와 JSONP 가 사용될 경우에는 자동으로 false 로 세팅됩니다. 더 자세한 내용은 함수들의 사용법을 살펴 보십시오.

만일 서버가 HTTP 인증을 요구한다면 username 과 password 옵션을 사용할 수 있습니다.

Ajax 사용 시 시간제한을 두어 사용자에게 그 내용을 제공하는 것이 좋습니다. 요청시간은 $.ajaxSetup() 에서 timeout 옵션값을 조절하는 것이 좋습니다.

기본적으로 지속적인 요청에 대해 브라우저는 캐시에 있는 결과를 사용하려 합니다. 이런 부분을 해결하기 위해 cache 옵션을 false로 세팅하시기 바랍니다. 또한 결과가 마지막 요청 후에 변경되지 않았다면 ifModified을 true로 세팅하면 false를 반환받을 수 있습니다.

scriptCharset 옵션은 <script> 태그의 캐릭터셋을 명시적으로 설정할 수 있습니다. 만약 서버와 스크립트의 캐릭터 셋이 다를 경우 아주 유용한 옵션입니다.

Ajax 의 기본은 "비동기(asynchronous)" 입니다. async 옵션은 기본적으로 $.ajax() 에서 true 로 세팅되어 있습니다. 이 옵션을 false 로 바꾸면 동기식으로 전환됩니다.

$.ajax() 함수는 XMLHttpRequest 객체를 반환합니다. 일반적으로 jQuery는 내부적으로 이 객체를 처리합니다. 사용자 정의 함수에서는 xhr 의 옵션을 이용해서 가공을 할 수 있습니다. 반환된 객체는 대체로 삭제되지만 저수준 인터페이스에서는 요청에 대한 조작을 위해 사용할 수도 있습니다. 특히,.abort() 를 호출하면 객체가 완성되기 전에 요청을 중단할 수 있습니다.

jQuery.ajaxSettings.xhr 를 오버라이드해서 사용하는 예제입니다.

var _super = jQuery.ajaxSettings.xhr;
jQuery.ajaxSettings.xhr = function () {
    var xhr = _super(),
        getAllResponseHeaders = xhr.getAllResponseHeaders;

    xhr.getAllResponseHeaders = function () {
        if ( getAllResponseHeaders() ) {
            return getAllResponseHeaders();
        }
        var allHeaders = "";
        $( ["Cache-Control", "Content-Language", "Content-Type",
                "Expires", "Last-Modified", "Pragma"] ).each(function (i, header_name) {

            if ( xhr.getResponseHeader( header_name ) ) {
                allHeaders += header_name + ": " + xhr.getResponseHeader( header_name ) + "\n";
            }
            return allHeaders;
        });
    };
    return xhr;
};

Extending Ajax

jQuery 1.5부터, jQuery의 Ajax 는 더 유연하게 사용할 수 있도록 확장된 사전필터(prefilters), 컨버터(converters), 변환(transports)이 포함되어 있습니다. 이런 이점에 대해 더 많은 정보를 얻으시려면 Extending Ajax 페이지를 살펴 보십시오.

Additional Notes:

보안 문제로 인해 대부분의 "Ajax" 요청은 제한이 있습니다. 도메인, 서브 도메인, 프로토콜이 다른 상황에서의 조회는 사용하지 못합니다. Script 와 JSONP 요청은 이런 제약에서 자유롭습니다.

예 제  
서버에 데이터를 보내고 완료되면 사용자에게 알립니다.

$.ajax({
  type: "POST",
  url: "some.php",
  data: { name: "John", location: "Boston" }
}).done(function( msg ) {
  alert( "Data Saved: " + msg );
});

 

예 제  
HTML 페이지의 최신 버전을 요청합니다.

$.ajax({
  url: "test.html",
  cache: false
}).done(function( html ) {
  $("#results").append(html);
});

 

예 제  
XML 데이터를 서버에 보냅니다. processData 옵션값을 false로 하여 자동으로 데이터가 string으로 변환되는 것을 방지합니다.

var xmlDocument = [create xml document];
var xmlRequest = $.ajax({
  url: "page.php",
  processData: false,
  data: xmlDocument
});

xmlRequest.done(handleResponse);

 

예 제  
서버로 데이터를 보내고, 서버는 저장 후 특정 메시지를 보내 줍니다. 완료되면 로그 메시지를 갱신하고 실패하면 알림창을 나타냅니다.

var menuId = $("ul.nav").first().attr("id");
var request = $.ajax({
  url: "script.php",
  type: "POST",
  data: {id : menuId},
  dataType: "html"
});

request.done(function(msg) {
  $("#log").html( msg );
});

request.fail(function(jqXHR, textStatus) {
  alert( "Request failed: " + textStatus );
});

 

예 제  
JavaScript 파일을 로드하고 실행합니다.

$.ajax({
  type: "GET",
  url: "test.js",
  dataType: "script"
});

 

 

조금 쉬어가면서 작성했지만, 역시 역부족이네요. 사실 너무 길어서 필요한 것만 할까 생각했지만 그래도 처음부터 발번역을 했습니다. 나중에 개정판(?)이 될지는 모르겠지만 아마 고쳐야 할 부분이 너무 많습니다. 맨위에서 권고 드렸듯이 예제만 보는 것이 정신건강에 좋을 듯합니다. ^^;;;;;

그럼 즐프하세요.

※ 본 예제는 http://www.jquery.com 에 있는 내용임을 밝힙니다.

Posted by 1010
00.scala2014. 3. 28. 15:38
반응형

Scala file FAQ: How do I open and read files in Scala?

When you're writing Scala scripts, you often want to read text files. Fortunately it's pretty easy to openand read from a file in Scala. You can just use an approach like this:

import scala.io.Source

val filename = "fileopen.scala"
for (line <- Source.fromFile(filename).getLines()) {
  println(line)
}

As you can see, this approach uses the scala.io.Source class. Within the for loop I can now access each line of the file using the 'line' object, and in this case I'm printing each line using println.

A variation of this is to add the mkString function to the file-reading portion of that code, like this:

val fileContents = Source.fromFile(filename).getLines.mkString

Another nice file-reading example comes from Bruce Eckel's website:

val fileLines = io.Source.fromFile("Colors.scala").getLines.toList
fileLines.foreach(println)

As you can see from that example, you can read an entire text file into a Scala List with what appears to be only one line of source code.

Handling file exceptions

Of course you can generate exceptions when trying to open a file, and if you want to handle your exceptions, you use a syntax similar to the Java try/catch syntax, like this:

import scala.io.Source

val filename = "no-such-file.scala"
try {
  for (line <- Source.fromFile(filename).getLines()) {
    println(line)
  }
} catch {
  case ex: Exception => println("Bummer, an exception happened.")
}

If I change that Exception line to print my exception object, like this:

case ex: Exception => println(ex)

and then run this script again, I can see that this code throws a java.io.FileNotFoundException exception when it fails:

java.io.FileNotFoundException: no-such-file.scala (No such file or directory)

As a result, if I want to catch all the old Java exceptions like I used to, I can write a Scala script like this to catch the Java FileNotFoundException and IOException:

import scala.io.Source
import java.io.{FileReader, FileNotFoundException, IOException}

val filename = "no-such-file.scala"
try {
for (line <- Source.fromFile(filename).getLines()) {
  println(line)
}
} catch {
  case ex: FileNotFoundException => println("Couldn't find that file.")
  case ex: IOException => println("Had an IOException trying to read that file")
}


Posted by 1010
00.scala2014. 3. 28. 15:38
반응형

Scala XML FAQ: How do I load an XML URL in Scala? (How do I read/download the contents of an XML URL in Scala?)

To load the contents of an XML URL (web page) in Scala, such as an RSS news feed or RESTful web service, just use the load method of the Scala XML class:

val xml = XML.load("http://www.devdaily.com/rss.xml")

Here's an example of what this looks like in the Scala REPL:

scala> import scala.xml.XML
import scala.xml.XML

scala> val xml = XML.load("http://www.devdaily.com/rss.xml")
xml: scala.xml.Elem = 
<rss xml:base="http://www.devdaily.com" version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>

(output goes on for about ten more lines)

Once you have your XML object (an instance of the scala.xml.Elem class), you can search it as usual. Since my RSS feed includes an "item" tag, I can get the number of item tags in the XML contents:

scala> (xml \\ "item").length
res5: Int = 10

I can also do things like searching for "title" elements, such as getting the text from the first RSS title element:

scala> val firstTitle = (xml \\ "channel" \ "title") text
firstTitle: String = devdaily.com

As you can see, loading the contents of an XML URL in Scala is very easy.

Posted by 1010
00.scala2014. 3. 28. 15:37
반응형

Scala FAQ: How do I load an XML file in Scala? (How do I open and read an XML file in Scala?)

I demonstrated this in my earlier Scala XML - Searching XMLNS namespaces, XPath tutorial, but you can load an XML file in Scala like this:

import scala.xml.XML
val xml = XML.loadFile("/Users/al/Projects/Scala/yahoo-weather.xml")

Once you've loaded the file contents like that, you can manipulate them as desired, such as searching the XML using XPath constructs like this:

val temp = (xml \\ "channel" \\ "item" \ "condition" \ "@temp") text

In summary, if you need to load an XML file in Scala, I hope this has been helpful.

Posted by 1010
00.scala2014. 3. 28. 15:37
반응형

Problem: You want to write XML data to a file in a Scala application, such as saving application data or configuration information to a file.

Solution

Use the scala.xml.XML.save method to write a Scala literal to a file. Given this XML literal:

// create an XML variable
val portfolio = 
  <portfolio>
    <stocks>
      <stock>AAPL</stock>
      <stock>AMZN</stock>
      <stock>GOOG</stock>
    </stocks>
    <reits>
      <reit>Super REIT 1</reit>
    </reits>
  </portfolio>

write the literal to file with the save method:

// save the XML to a file
scala.xml.XML.save("portfolio.xml", portfolio)

This creates a plain-text file named portfolio.xml in the current directory, containing the XML literal shown.

As with any file-writing code, beware that XML.save can throw an exception:

scala> scala.xml.XML.save("/foo/bar/baz", portfolio)
java.io.FileNotFoundException: /foo/bar/baz (No such file or directory)

Additional save parameters

The save method lets you specify other parameters, including the encoding to use, whether or not to write an XML declaration, and whether or not to write a DOCTYPE declaration.

To write the data to a file with encoding information, use this approach:

XML.save("portfolio.xml", portfolio, "UTF-8", true, null)

This results in the following header being added to the file:

<?xml version='1.0' encoding='UTF-8'?>

To add a DOCTYPE to the file, first import the necessary classes:

import scala.xml.dtd.{DocType, PublicID}

Then create a DocType instance, and save the file with that instance:

val doctype = DocType("html",
  PublicID("-//W3C//DTD XHTML 1.0 Strict//EN",
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"),
  Nil)

XML.save("portfolio.xml", portfolio, "UTF-8", true, doctype)

With this configuration, the following DOCTYPE line is added to the output file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

The scala.xml package also includes a Utility object with a small collection of useful methods that let you sort node attributes, trim elements, remove comments, and more.

Pretty printing

If it’s important that the XML can be easily read by a human being, it’s best to use the PrettyPrinter class to make sure the XML is “human readable.” But because the PrettyPrinter returns a String, you’ll need to write it to a file using another method. I have my own FileUtils class, so the process looks like this:

val portfolio =
  <portfolio>
    <stocks>
      <stock>AAPL</stock><stock>AMZN</stock><stock>GOOG</stock>
    </stocks>
    <reits><reit>Super REIT 1</reit></reits>
  </portfolio>

// 80 characters wide, 2 character indentation
val prettyPrinter = new scala.xml.PrettyPrinter(80, 2)
val prettyXml = prettyPrinter.format(portfolio)
FileUtils.save("portfolio.xml", prettyXml)


Posted by 1010
00.scala2014. 3. 28. 14:23
반응형

Problem: You want to dynamically generate XML from your Scala source code, such as creating output for a SOAP web service.

Solution

A great feature of Scala’s XML support is that you can interweave XML and regular Scala source code together. This lets you dynamically generate XML from your Scala code.

To create XML with dynamic, embedded data, just put your Scala code in curly braces inside the XML tags, as shown in the following example:

scala> val name = "Bill"
name: String = Bill

scala> val age = 42
age: Int = 42

scala> val p = <person><name>{name}</name><age>{age}</age></person>
p: scala.xml.Elem = <person><name>Bill</name><age>42</age></person>

In this example, the Scala variables name and age are put inside curly braces, inside the XML literals. The variable p in the REPL results shows that they’re translated to their values (Bill and 42, respectively). Methods and other expressions can be used in the same way.

This ability to weave Scala code and XML together is similar to using a templating system, and is a great way to generate dynamic XML output, including output like an RSS news feed, all forms of business data, or a simple XHTML UL/LI tag combination:

scala> val fruits = List("apple", "banana", "orange")
fruits: List[java.lang.String] = List(apple, banana, orange)

scala> val ul = <ul>{fruits.map(i => <li>{i}</li>)}</ul>
ul: scala.xml.Elem = <ul><li>apple</li><li>banana</li><li>orange</li></ul>

scala> println(ul)
<ul><li>apple</li><li>banana</li><li>orange</li></ul>

You can use the same technique to generate XHTML <select> and <option> tags, such as for a list of states or credit cards options, and any other form of XML data.

Discussion

As shown in the fruits example, XML literals can contains Scala code in curly braces, and that code can include additional XML literal values, which can contain Scala code. This nesting of Scala and XML can continue to go deeper, as needed.

To explain how this works, let’s look at the code again:

val ul = <ul>{fruits.map(i => <li>{i}</li>)}</ul>

Here’s how this code works:

  • The XML expression is enclosed in the matching <ul> tags.
  • The curly braces begin the fruits.map Scala expression.
  • <li> tags are embedded in the code block passed to the map method.
  • The variable i is enclosed in curly braces inside the <li> tags, where it will be replaced by its values as the map method executes.

If you’ve used XML/HTML templating tools previously, you can appreciate the power of this approach.

NodeBuffer

The NodeBuffer class provides another nice way to dynamically build XML. The following example shows how to build a set of <li> tags as a NodeBuffer, and then insert those elements into a final <ul>tag:

scala> val x = new xml.NodeBuffer
x: scala.xml.NodeBuffer = ArrayBuffer()

scala> x += <li>apple</li>
res0: x.type = ArrayBuffer(<li>apple</li>)

scala> x += <li>banana</li>
res1: x.type = ArrayBuffer(<li>apple</li>, <li>banana</li>)

scala> val ul = <ul>{x}</ul>
ul: scala.xml.Elem = <ul><li>apple</li><li>banana</li></ul>

NodeBuffer is a simple convenience class that extends ArrayBuffer[Node]. It adds one method named &+that appends the given object to the buffer, and returns a this reference for convenience. This lets you write a “fluent” style of code like this, if you prefer:

val nb = new xml.NodeBuffer
val nb2 = nb &+ <li>apple</li> &+ <li>banana</li> &+ <li>cherry</li>

See Recipe 5.9 of the Scala Cookbook, “Supporting a Fluent Style of Programming,” for more information on supporting and using this coding style.

Posted by 1010
00.scala2014. 3. 28. 13:43
반응형

After writing a Java REST (RESTful) client using Apache HttpClient, I turned around and modified that code to be a Scala REST client, also using the Apache HttpClient library.

Here then, without much introduction, is the source code for a Scala REST client example, which demonstrates how to read information from the Yahoo Weather API, which is actually an RSS feed. As a result, this example also demonstrates how to search an XML document for the information you want, using the built-in Scala XML parsing capabilities.

package tests

import java.io._
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.client.ClientProtocolException
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.DefaultHttpClient
import scala.collection.mutable.StringBuilder
import scala.xml.XML

object ScalaApacheHttpRestClient {

  def main(args: Array[String]) {
  
    // (1) get the content from the yahoo weather api url
    val content = getRestContent("http://weather.yahooapis.com/forecastrss?p=80020&u=f")
    
    // (2) convert it to xml
    val xml = XML.loadString(content)
    assert(xml.isInstanceOf[scala.xml.Elem])  // needed?

    // (3) search the xml for the nodes i want
    val temp = (xml \\ "channel" \\ "item" \ "condition" \ "@temp") text
    val text = (xml \\ "channel" \\ "item" \ "condition" \ "@text") text

    // (4) print the results
    val currentWeather = format("The current temperature is %s degrees, and the sky is %s.", temp, text.toLowerCase())
    println(currentWeather)
  }
  
  /**
   * Returns the text content from a REST URL. Returns a blank String if there
   * is a problem.
   */
  def getRestContent(url:String): String = {
    val httpClient = new DefaultHttpClient()
    val httpResponse = httpClient.execute(new HttpGet(url))
    val entity = httpResponse.getEntity()
    var content = ""
    if (entity != null) {
      val inputStream = entity.getContent()
      content = io.Source.fromInputStream(inputStream).getLines.mkString
      inputStream.close
    }
    httpClient.getConnectionManager().shutdown()
    return content
  }

}

Description

As you can see from the main method, the code is pretty simple, only involving a few steps. The getRestContent function does a lot of the dirty work involved in getting the content from a REST URL. (That function can probably be written better, as I'm ignoring a number of exceptions that can happen.)

There is also some magic involved in processing the XML using the Scala XML library. It took me longer to figure out the syntax to search the XML for the nodes I wanted than it did to write the rest of this example, so I'll discuss that Scala XML syntax in another tutorial.

As I mentioned in my earlier Java RESTful client example, there are several other good ways of creating REST clients in Java and Scala, including using the Jersey project, or the Apache CXF project. Those libraries are specifically geared more towards web services and implementing the API of the Java JSRs that describe web services, while the Apache HttpClient library just simplifies the process of creating HTTP clients. Which one you use is up to you, and I hope/plan to write RESTful clients in Scala using each of those libraries.

In trying to keep this short, I'll leave the example and discussion at that. As usual, if you have any questions, comments, or improvements, just leave a note in the comments section below.

Posted by 1010
00.scala2014. 3. 28. 13:42
반응형

Scala JDBC FAQ: How can I use the Java JDBC API in my Scala application?

If you want to use a SQL database with your Scala applications, it's good to know you can still use the traditional Java JDBC programming library to access databases. I just ran a simple JDBC connectionand SQL SELECT test, and everything seems to work just as it does in Java.

A Scala, JDBC, and MySQL example

Without any further introduction, here's the source code for a complete Scala class (an object, actually) that connects to a MySQL database using nothing but plain old JDBC. In this example I'm connecting to a MySQL database server on my local computer, and then running a SQL SELECT query against theuser table of the mysql database:

package jdbc

import java.sql.DriverManager
import java.sql.Connection

/**
 * A Scala JDBC connection example by Alvin Alexander,
 * http://alvinalexander.com
 */
object ScalaJdbcConnectSelect {

  def main(args: Array[String]) {
    // connect to the database named "mysql" on the localhost
    val driver = "com.mysql.jdbc.Driver"
    val url = "jdbc:mysql://localhost/mysql"
    val username = "root"
    val password = "root"

    // there's probably a better way to do this
    var connection:Connection = null

    try {
      // make the connection
      Class.forName(driver)
      connection = DriverManager.getConnection(url, username, password)

      // create the statement, and run the select query
      val statement = connection.createStatement()
      val resultSet = statement.executeQuery("SELECT host, user FROM user")
      while ( resultSet.next() ) {
        val host = resultSet.getString("host")
        val user = resultSet.getString("user")
        println("host, user = " + host + ", " + user)
      }
    } catch {
      case e => e.printStackTrace
    }
    connection.close()
  }

}

As you can see, this Scala JDBC database connection example looks just like Java JDBC, which you can verify from my very old JDBC connection example and JDBC SQL SELECT example.

If you're new to JDBC and the MySQL URL shown above looks weird because I'm accessing the "mysql" database in the MySQL database server, remember that the general MySQL connection URL looks like this:

val url = "jdbc:mysql://hostname/database_name"

and if I was instead connecting to a database named drupal7, the MySQL URL would look like this instead:

val url = "jdbc:mysql://localhost/drupal7"


Posted by 1010
00.scala2014. 3. 28. 13:41
반응형

Scala FAQ: Can you share some examples of using tuples in Scala?

Getting started with tuples

A Scala tuple is a class that can contain a miscellaneous collection of elements. I like to think of them as a little bag or container you can use to hold things and pass them around.

You create a tuple with the following syntax, enclosing its elements in parentheses. Here's a tuple that contains an Int and a String:

val stuff = (42, "fish")

This creates a specific instance of a tuple called a Tuple2, which we can demonstrate in the REPL:

scala> val stuff = (42, "fish")
stuff: (Int, java.lang.String) = (42,fish)

scala> stuff.getClass
res0: java.lang.Class[_ <: (Int, java.lang.String)] = class scala.Tuple2

A tuple isn't actually a collection; it's a series of classes named Tuple2Tuple3, etc., through Tuple22. You don't have to worry about that detail, other than knowing that you can have anywhere from two to twenty-two items in a tuple. (And in my opinion, if you have twenty-two miscellaneous items in a bag, you should probably re-think your design.)

Accessing tuple elements

You can access tuple elements using an underscore syntax. The first element is accessed with _1, the second element with _2, and so on, like this:

scala> val things = ("a", 1, 3.5)
things: (java.lang.String, Int, Double) = (a,1,3.5)

scala> println(things._1)
a

scala> println(things._2)
1

scala> println(things._3)
3.5

Use variable names to access tuple elements

When referring to a Scala tuple you can also assign names to the elements in the tuple. I like to do this when returning miscellaneous elements from a method. To demonstrate the syntax, let's create a very simple method that returns a tuple:

def getUserInfo = ("Al", 42, 200.0)

Now we can call that method, and assign the tuple results directly to variables, like this:

val(name, age, weight) = getUserInfo

Here's what this looks like in the REPL:

scala> def getUserInfo = ("Al", 42, 200.0)
getUserInfo: (java.lang.String, Int, Double)

scala> val(name, age, weight) = getUserInfo
name: java.lang.String = Al
age: Int = 42
weight: Double = 200.0

It's shown in the REPL results, but we'll further confirm that we can indeed access the values by variable name:

scala> name
res4: java.lang.String = Al

scala> age
res5: Int = 42

scala> weight
res6: Double = 200.0

That's pretty nice.

In a cool, related feature, if you only want to access some of the elements, you can ignore the others by using an underscore placeholder for the elements you want to ignore. Imagine you want to ignore theweight in our example:

scala> val(name, age, _) = getUserInfo
name: java.lang.String = Al
age: Int = 42

Or suppose you want to ignore the age and weight:

scala> val(name, _, _) = getUserInfo
name: java.lang.String = Al

Again, that's good stuff.

Iterating over a Scala tuple

As mentioned, a tuple is not a collection; it doesn't descend from any of the collection traits or classes. However, you can treat it a little bit like a collection by using its productIterator method.

Here's how you can iterate over the elements in a tuple:

scala> val t = ("Al", 42, 200.0)
t: (java.lang.String, Int, Double) = (Al,42,200.0)

scala> t.productIterator.foreach(println)
Al
42
200.0

The tuple toString method

The tuple toString method gives you a nice representation of a tuple:

scala> t.toString
res9: java.lang.String = (Al,42,200.0)

scala> println(t.toString)
(Al,42,200.0)

Creating a tuple with ->

In another cool feature, you can create a tuple using this syntax:

1 -> "a"

This creates a Tuple2, which we can demonstrate in the REPL:

scala> 1 -> "a"
res1: (Int, java.lang.String) = (1,a)

scala> res11.getClass
res2: java.lang.Class[_ <: (Int, java.lang.String)] = class scala.Tuple2

You'll see this syntax a lot when creating maps:

scala> val map = Map(1->"a", 2->"b")
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b)


Posted by 1010
00.scala2014. 3. 28. 13:41
반응형

Scala Map FAQ: How can I iterate/loop over a Scala Map?

There are several different ways to iterate over a Scala Map, and the method you choose depends on the problem you need to solve.

To get started with our examples, let's create a simple Map we can work with:

scala> val m1 = Map("fname" -> "Al", "lname" -> "Alexander")

Iterating over Scala maps

Once you have a Map, you can iterate over it using several different techniques. For me, this is by far the easiest technique:

scala> for ((k,v) <- m1) printf("key: %s, value: %s\n", k, v)
key: fname, value: Al
key: lname, value: Alexander

This page has some other Map and for loop examples, which I've reproduced here:

// version 1 (tuples)
m1 foreach (x => println (x._1 + "-->" + x._2))

// version 2 (foreach and case)
m1 foreach {case (key, value) => println (key + "-->" + value)}

You can choose whatever format you prefer. Scala is beginning to remind me of the Perl slogan: "There's more than one way to do it", and this is good, because you can choose whichever approach makes the most sense for the problem at hand.

Scala Map, keys, foreach, and tuples

To demonstrate a more "real world" example of looping over a Scala Map, while working through some programming examples in the book, Programming Collective Intelligence, I decided to code them up in Scala, and I wanted to share the approaches I prefer using the Scala foreach and for loops.

To begin with, I defined my Scala Map like this:

val p1Ratings = Map("Lady in the Water"-> 3.0, 
                    "Snakes on a Plane"-> 4.0,
                    "You, Me and Dupree"-> 3.5)

In my case, when I'm iterating over the Map I'm really just interested in the Map keys, so the cleanest way to loop over every Map element is like this:

p1Ratings.keys.foreach( (movie) => 
  if (p2Ratings.contains(movie)) similarItems += (movie -> true)
)

While I chose that looping method in my code, I could also use the "tuples" approach, where movie is a Tuple, and I only use the first element of the Tuple, which happens to be my keys:

p1Ratings foreach ( (movie) => 
  if (p2Ratings.contains(movie._1)) similarItems += (movie._1 -> true)
)

In that approach, I ignore the second element of each Tuple, because I don't need it. (Which is why I don't like this approach for this instance.)

In a similar approach, I loop over the Map as shown next, creating a field named rating1 which I again don't use because I don't need it:

for ((movie1, rating1) <- p1Ratings) {
  if (p2Ratings.contains(movie1)) similarItems += (movie1 -> true)
}

These last two approaches will work better, and look a little more logical, if you need to access the key and value for each map element, but in my case, since I don't need to values, I'm using the first approach shown above.

Posted by 1010