본문 바로가기
윅스 (Wix) 홈페이지 만들기/윅스 코딩 (Wix Code - Corvid)

윅스 (Wix) 코딩 - 프로미스(Promises) (Wix Code: Working with Promises)

by 라임쥬서(Lime Juicer) 2020. 5. 5.
반응형

윅스 (Wix) 코딩 - 프로미스(Promises) (Wix Code: Working with Promises)

 

 

 

설명)

 

비동기 코드는 작성한 순서대로 줄 단위로 실행되지 않는 코드입니다. 윅스 코드(Wix Code)에서는 즉시 실행을 완료할 수 없는 함수를 호출할 때 비동기 코드가 발생하여 약속을 반환합니다. 또한 페이지 코드에서 작성한 백엔드 함수를 호출하면 비동기적으로 호출됩니다.

 

예를 들어, find() 함수를 사용하여 데이터베이스 컬렉션 중 하나에서 조회를 실행하면 조회가 실행되고 결과가 리턴되는 데 시간이 걸립니다. 따라서 쿼리 결과를 사용하기 전에 작업이 완료될 때까지 기다려야합니다.

 

find( ) 함수가 프로미스(Promise)를 반환하는 다음 코드 단편을 고려합니다.

 

 

console.log("1")

wixData.query("myCollection")
  .find()
  .then( (results) => {
    console.log("2");
  } );

console.log("3");

 

 

 

다음 내용이 콘솔에 기록됩니다.

 

1
3
2

 

 

 

console.log( ) 호출이 코드에서 이 순서대로 나타나지 않더라도 3이 2보다 먼저 기록됩니다. 그 이유는 2의 로깅은 쿼리가 끝나면 발생하기 때문에 나머지 코드는 계속 실행되기 때문입니다.

이 글에서는 비동기적으로 실행되는 Wix Code API의 함수로 작업하는 방법에 대해 설명합니다. 우리는 이러한 함수를 호출하고 실행을 마칠 때까지 기다리는 다양한 방법을 논의합니다. 자바스크립트(JavaScript)에서 비동기 프로그래밍에 대한 일반적인 논의는 하지 않습니다. 자세한 내용은 여기를 참조합니다.

 

 

 

 

프로미스 (Promise)

프로미스(Promise)는 비동기 통신에 의존하기 때문에 약속이 생성될 때 반드시 알려지지 않은 값을 나타냅니다. 프로미스(Promise)을 반환하는 함수는 미래의 어떤 시점에서 최종적으로 반환 값을 생성하기 위해 계약을 반환합니다. 프로미스(Promise)는 가치가 드디어 알려지면 성취되거나 해결된다고 합니다.

 

함수에서 반환된 약속을 사용하여 작업하는 두 가지 주요 방법이 있습니다.

 

- then( ) - 좀 더 복잡하지만 좀 더 제어 할 수 있습니다.

- async/await - 동기식인 것처럼 비동기 코드로 작업할 수 있습니다.

 

 

then( )

프로미스(Promise)의 then( )을 사용하여 프로미스(Promise)가 해결할 때 실행할 함수를 지정할 수 있습니다. 지정된 함수는 약속이 해결할 값을 받습니다. 따라서 프로미스(Promise)의 해결된 값에 의존하는 코드는 then( )에 배치해야합니다.

예를 들어 컬렉션에서 일부 데이터를 검색하여 표(Table)에 표시하려고 한다고 가정해봅니다. 데이터 검색은 비동기 작업이므로 쿼리 결과를 사용하여 표(Table)의 데이터를 설정하기 전에 완료될 때까지 기다려야합니다. find( ) 함수는 질의를 수행하고 표(Table)를 반환합니다. 그래서 then( )은 질의가 끝날 때 실행되는 함수를 정의합니다. 이 함수는 쿼리 결과를 받아 표(Table)의 행 데이터를 설정하는 데 사용합니다. then( ) 다음에 나오는 코드는 쿼리가 시작된 후 쿼리가 끝나기 전에 실행됩니다. 따라서 쿼리 결과를 사용할 수 없습니다.

 

import wixData from 'wix-data';

$w.onReady( function () {
  wixData.query("myCollection")
    .find()
    .then( (results) => {
      // this will only run once the query has returned results
      $w("#myTable").rows = results.items;
    } );
  // code here will run before the query has returned results
} );

 

 

 

 

Multiple .then( ) Calls

때로는 다른 비동기 함수에서 반환한 프로미스(Promise)의 then( ) 내에서 다른 비동기 함수를 호출해야 할 수도 있습니다.

 

예를 들어 fetch( ) 함수를 사용하여 타사 서비스에서 데이터를 검색하려고 한다고 가정해봅니다. 이 작업은 타사에서 응답을 기다릴 때까지 비동기적입니다. 그런 다음 응답을 JSON으로 읽고 싶습니다. 응답 객체의 json( ) 함수도 비동기입니다.

 

다음 중 하나를 다른 것으로 ( ) 내포할 필요가 있다고 생각할 수 있습니다.

 

fetch( url, {method: 'get'} )
  .then( (response) => {
    return response.json()
      .then( (json) => {
        // do something with the json response
      } );
  } );

 

 

 

그러나 then( ) 자체가 프로미스(Promise)를 반환하기 때문에 반환된 프로미스(Promise)에서 다른 then( )을 호출할 수 있습니다. 결론은 연속적인 then( ) 호출을 체인화하여 다른 비동기 연산을 수행할 수 있음을 의미합니다.

 

즉 위의 코드는 다음과 같이 작성해야합니다.

 

fetch( url, {method: 'get'} )
  .then( response => response.json() )
  .then( (json) => {
    // do something with the json response
  } );

 

 

여기서 2번째 줄의 then( )은 fetch( ) 호출에 의해 반환된 프로미스(Promise)의 then( )입니다. 그리고 3번째 줄의 then( )은 json( ) 호출에 의해 반환된 프로미스(Promise)의 then( )입니다. 첫 번째 then( )은 fetch( ) 호출이 끝난 후에만 ​​실행되고 두 번째 then( )은 json( ) 호출이 끝난 후에만 ​​실행됩니다.

 

 

 

 

 

Returning in a .then( )

또 다른 오해는 then( ) 안의 return을 사용할 때 일어나는 오해입니다. 일부 사람들은 프로미스(Promise)가 해결하는 값이 then( )이 있는 함수의 반환 값으로 사용되는 것으로 잘못 생각합니다.

 

예를 들어 자동차에 대한 페이지가 있다고 가정해봅니다. 이 페이지에는 사용자가 자동차 모델을 선택하는 데 사용하는 드롭다운이 있습니다. 선택을 하면 특정 자동차 모델에 대한 쿼리를 수행하고 일치하는 모든 항목이 있는 표(Table)를 채웁니다.

 

find( ) 프로미스(Promise)가 해결되면 queryCars( ) 함수가 배열로 자동차 항목을 반환한다고 생각하는 코드를 작성할 수 있습니다.

 

import wixData from 'wix-data';

export function modelDropdown_change() {
  let model = $w("#modelDropdown").value;
  $w("#resultsTable").rows = queryCars(model);
}

// This will not work as expected
function queryCars(model) {
  wixData.query("cars")
    .eq("model", model)
    .find()
    .then( (results) => {
      return results.items;
    } );
}

 

 

 

그러나 위의 코드는 예상대로 작동하지 않습니다. 왜 작동하지 않는지, 문제를 해결하기위해 해야​​할 일을 이해합시다.

results.items를 반환하면 queryCars( ) 함수의 반환 값으로 반환하지 않습니다. 오히려, 그것은 then( )에 전달된 화살표 함수의 반환 값으로 반환됩니다. 이는 queryCars( ) 함수에서 아무것도 반환되지 않음을 의미합니다. 따라서 우리가 queryCars( )를 호출하여 표(Table)의 행을 설정하면 반환할 것이 없습니다.

 

이 상황을 해결하려면 프로미스(Promise)의 then( ) (또는 then( ) 체인)의 결과를 반환해야합니다. 그렇게하기 위해 프로미스(Promise)를 만든 체인을 시작하기 전에 단순히 return 을 추가합니다. 그러면 체인의 최종 링크가 반환됩니다.

 

체인은 다음과 같습니다.

- .query( ) - 쿼리 만들기 - WixDataQuery 객체를 반환합니다.

- .eq( ) - 쿼리 수정 - WixDataQuery 객체를 반환합니다.

- .find( ) - 쿼리 실행 - 프로미스(Promise)를 반환합니다.

- .then( ) - 해결 방법 정의 - 프로미스(Promise)를 반환합니다.

 

체인의 시작 부분에 return 을 추가한다는 것은 그 때의 마지막에서 반환된 프로미스(Promise)를 반환한다는 것을 의미합니다. then( )에서 반환 된 값은 프로미스(Promise)이기 때문에 queryCars( ) 함수를 호출할 때 이를 염두에 두어야합니다.

 

 

즉, 수정된 코드는 다음과 같아야합니다.

 

import wixData from 'wix-data';

export function modelDropdown_change() {
  let model = $w("#modelDropdown").value;
  queryCars(model)
    .then( (items) => {
      $w("#resultsTable").rows = items;
    } );
}

// The added `return` on line 13 fixes the problem
function queryCars(model) {
  return wixData.query("cars")
    .eq("model", model)
    .find()
    .then( (results) => {
      return results.items;
    } );
}

 

 

여기서 queryCars( ) 함수는 쿼리 결과의 항목을 확인하는 프로미스(Promise)를 반환합니다. 따라서 우리가 queryCars( ) 함수를 호출할 때 프로미스(Promise)와 같이 처리하고 then( )을 사용하여 해결된 값을 사용하여 표(Table)의 행 데이터를 설정해야합니다.

 

 

 

 

백엔드 디버깅 (Debugging on the Backend)

프로미스(Promise) 자체가 클라이언트 측 코드로 반환되지 않는 한, 백엔드 코드의 프로미스(Promise) then( ) 내부에서 만들어진 console.log( )에 대한 호출은 개발자 콘솔에 기록되지 않습니다.

 

 

예를 들어, 다음 백엔드 코드를 고려해봅니다.

 

export function usePromise() {
  return fetch('https://site.com/api?q=query', {method: 'get'})
    .then( (response) => {
      console.log(response.status);
  } );
}

 

 

작성된 것처럼 클라이언트 측에서 usePromise를 호출하면 3행의 메시지가 개발자 콘솔에 기록됩니다. 그러나 2행의 return을 제거하고 클라이언트 측에서 usePromise를 호출하면 3행의 메시지가 개발자 콘솔에 기록되지 않습니다.

 

 

 

 

오류 처리 (Error Handling)

비동기 프로세스는 여러 가지 이유로 실패할 수 있습니다. 예를 들어 다른 서버와 통신하는 fetch( )와 같은 함수를 호출하면 통신 오류로 인해 호출이 실패할 수 있습니다. 프로미스(Promise)이 성공적으로 해결되지 않으면 거부하겠다고 말합니다. then( ) 체인 끝에 catch( )를 추가하여 거부를 처리할 수 ​​있습니다. catch( )는 프로미스(Promise)이 거부하는 값 (대개는 오류)을 받습니다.

컬렉션에서 데이터를 가져와서 표(Table)에 표시하는 예제로 돌아가보겠습니다. 다음과 같이 catch( )를 추가하여 오류를 처리할 수 ​​있습니다.

 

import wixData from 'wix-data';

$w.onReady( function () {
  wixData.query("myCollection")
    .find()
    .then(results => $w("#myTable").rows = results.items)
    .catch(error => {
      // handle your error here
    } );
} );

 

 

 

 

비동기/대기 (async/await)

프로미스(Promise)와 함께 then( )을 사용하면 프로미스(Promise)가 해결될 때 실행할 코드를 정의할 수 있으며 동시에 then( ) 뒤에 오는 코드가 있으면 실행을 계속할 수 있습니다. 프로미스(Promise)을 반환하는 함수로 작업하는 또 다른 옵션은 다른 코드의 실행으로 넘어가기 전에 프로미스(Promise)가 해결될 때까지 기다리는 것입니다. async/await를 사용하면 그렇게 할 수 있습니다.

프로미스(Promise)를 반환하는 함수를 호출할 때 기다리고 있습니다. 프로미스(Promise)가 해결될 때까지 코드 실행을 일시 중지합니다. await를 사용하려면 해당 함수가 비동기 함수임을 선언해야합니다.

 

다시 한번, 컬렉션에서 데이터를 가져 와서 표(Table)에 표시하는 예제로 돌아가보겠습니다. 그러나 then( )을 사용하는 대신 find( ) 함수가 반환한 프로미스(Promise)를 처리하기 위해 async/await를 사용합니다.

 

then( )을 사용할 때 우리는 다음과 같은 코드를 작성했습니다 :

 

import wixData from 'wix-data';

$w.onReady( function () {
  wixData.query("myCollection")
    .find()
    .then( (results) => {
      // this will only run once the query has returned results
      $w("#myTable").rows = results.items;
    } );
  // code here will run before the query has returned results
} );

 

 

async/await을 사용하면 대신 다음과 같은 코드를 작성할 수 있습니다.

 

import wixData from 'wix-data';

$w.onReady( async function () { 
  const results = await wixData.query("myCollection").find(); 
  // the next line will run only after the query has finished
  $w("#table1").rows = results.items;
} );

 

 

여기서는 3행에서 onReady( ) 함수에 전달된 콜백 함수가 비동기 함수로 선언된 것을 볼 수 있습니다. find( ) 함수가 호출되면 await을 사용하여 호출됩니다. 따라서 쿼리가 실행될 때 find( ) 함수의 프로미스(Promise)가 해결될 때까지 실행이 대기합니다. 쿼리가 완료되면 쿼리 결과가 결과 변수에 저장되며 이 결과 변수를 사용하여 표(Table)의 행 데이터를 설정할 수 있습니다.

 

비동기 함수를 만들면 해당 함수는 프로미스(Promise)를 반환합니다. 따라서 이 함수를 호출하면 이 문서에서 논의된 접근 방법 중 하나를 사용하여 반환하는 프로미스(Promise)를 처리해야합니다.

 

예를 들어, 다음은 지정된 이름을 가진 항목을 찾기위해 컭렉션을 조회하는 비동기 함수입니다.

 

import wixData from 'wix-data';

//...

async function findName(name) {
  const results = await wixData.query("myCollection")
    .eq("name", name)
    .find();
  return results.items[0];
}

 

then( )을 사용하여 이 함수를 호출할 수 있습니다.

 

$w.onReady( function () {
  findName("Bob")
    .then(item => console.log(item));
} );

 

 

또는 async/await를 사용하여 호출할 수 있습니다.

 

$w.onReady( async function () {
  const item = await findName("Bob");
  console.log(item);
} );

 

 

 

오류 처리 (Error Handling)

async/await를 사용하면 일반적인 try/catch 블록을 사용하여 프로미스(Promise) 거부를 처리합니다.

 

import wixData from 'wix-data';

$w.onReady( async function () { 
  try {
    const results = await wixData.query("myCollection").find(); 
    $w("#table1").rows = results.items;
  }
  catch(error) {
    // handle the error here
  }
} );

 

 

 

 

 

연관된 토픽)

 

 

윅스 홈페이지 만들기 101

윅스 (Wix) 홈페이지 만들기 101 - E-Book - Index

 

윅스 (Wix) 홈페이지 만들기 101 - E-Book - Index

윅스 (Wix) 홈페이지 만들기 101 - E-Book - Index 윅스 (Wix.com) 윅스 ADI & 템플릿 (Wix ADI & 템플릿) 윅스 웹에디터 (Wix Editor) 윅스 코딩 (Wix Code - Corvid) 윅스 해커톤 (Wix Hackathon)

limejuicer.tistory.com

 

출처 :

https://support.wix.com/en/article/wix-code-working-with-promises

 

반응형

댓글