>웹 프론트엔드 >JS 튜토리얼 >JavaScript_기본지식 중 Promise 사용법에 대한 자세한 설명

JavaScript_기본지식 중 Promise 사용법에 대한 자세한 설명

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB원래의
2016-05-16 15:53:091851검색

많은 언어에서는 일반 시퀀스와 유사한 비동기 패턴을 처리하기 위해 promise, deferred 또는 future라는 흥미로운 솔루션 라이브러리를 포함합니다. JavaScript Promise는 긴밀하게 결합된 인터페이스 대신 우려사항의 분리를 촉진할 수 있습니다. 이 문서에서는 Promises/A 표준을 기반으로 하는 JavaScript Promise에 대해 설명합니다. [http://wiki.commonjs.org/wiki/Promises/A]

Promise 사용 사례:

  • 실행규칙
  • 다중 원격 검증
  • 시간 초과 처리
  • 원격 데이터 요청
  • 애니메이션
  • 애플리케이션 로직에서 이벤트 로직을 분리합니다
  • 콜백 함수의 삼각관계 제거
  • 병렬 비동기 작업 제어

JavaScript Promise는 미래에 값을 반환하겠다고 약속하는 객체입니다. 동작이 잘 정의된 데이터 개체입니다. Promise에는 세 가지 상태가 있습니다:

  1. 보류 중(미정)
  2. 거부됨
  3. 해결됨

거부되거나 완료된 약속은 해결된 것으로 간주됩니다. 약속은 보류 중에서 해결됨으로만 이동할 수 있습니다. 그 이후에는 약속의 상태가 변경되지 않습니다. Promise는 해당 처리가 완료된 후에도 오랫동안 존재할 수 있습니다. 즉, 처리 결과를 여러 번 얻을 수 있습니다. promise.then()을 호출하여 결과를 얻습니다. 이 함수는 promise에 해당하는 처리가 완료될 때까지 반환되지 않습니다. 우리는 여러 가지 약속을 유연하게 하나로 묶을 수 있습니다. 이렇게 연결된 "then" 함수는 새로운 약속이나 가장 빠른 약속을 반환해야 합니다.
이 스타일을 사용하면 동기 코드를 작성하는 것처럼 비동기 코드를 작성할 수 있습니다. 주로 약속을 결합하여 달성됩니다:

  • 스택형 작업: 동일한 Promise에 해당하는 여러 작업이 코드에 분산되어 있습니다.
  • 병렬 작업: 여러 Promise가 동일한 Promise를 반환합니다.
  • 연속 작업: 하나의 약속을 실행한 후 다른 약속을 실행합니다.
  • 위의 조합입니다.

왜 귀찮게 하나요? 그냥 기본 콜백 기능을 사용할 수는 없나요?

콜백 기능 문제

콜백 함수는 클릭을 기반으로 양식 유효성을 검사하거나 REST 호출 결과를 저장하는 등 단순 반복 이벤트에 적합합니다. 콜백 함수는 또한 하나의 콜백 함수가 REST 함수를 호출하고, REST 함수에 대한 새 콜백 함수를 설정하고, 이 새 콜백 함수가 다른 REST 함수를 호출하는 등의 코드 체인을 생성합니다. 코드의 수평적 성장은 수직적 성장보다 큽니다. 콜백 함수는 결과가 필요할 때까지 간단해 보이며 다음 줄 계산에 즉시 사용하기 위해 결과가 필요합니다.

'use strict';
var i = 0;
function log(data) {console.log('%d %s', ++i, data); };
 
function validate() {
  log("Wait for it ...");
  // Sequence of four Long-running async activities
  setTimeout(function () {
   log('result first');
   setTimeout(function () {
     log('result second');
     setTimeout(function () {
      log('result third');
      setTimeout(function () {
        log('result fourth')
      }, 1000);
     }, 1000);
   }, 1000);
  }, 1000);
 
};
validate();

비동기 작업을 시뮬레이션하기 위해 타임아웃을 사용합니다. 예외를 관리하는 방법은 고통스럽고 다운스트림 동작을 쉽게 이용할 수 있습니다. 콜백을 작성할 때 코드 구성이 혼란스러워집니다. 그림 2는 NodeJS REPL에서 실행할 수 있는 모의 유효성 검사 흐름을 보여줍니다. 다음 섹션에서는 파멸의 피라미드 패턴에서 지속적인 약속으로 이동해 보겠습니다.

그림

'use strict';
var i = 0;
function log(data) {console.log('%d %s', ++i, data); };
 
// Asynchronous fn executes a callback result fn
function async(arg, callBack) {
  setTimeout(function(){
   log('result ' + arg);
   callBack();
  }, 1000);
};
 
function validate() {
  log("Wait for it ...");
  // Sequence of four Long-running async activities
  async('first', function () {
   async('second',function () {
     async('third', function () {
      async('fourth', function () {});
     });
   });
  });
};
validate();

NodeJS REPL 실행 결과

$ node scripts/examp2b.js
1 Wait for it ...
2 result first
3 result second
4 result third
5 result fourth
$

저는 AngularJS 동적 유효성 검사가 해당 테이블의 값을 기반으로 양식 항목의 값을 동적으로 제한하는 상황에 직면한 적이 있습니다. 제한 항목의 유효한 값 범위는 REST 서비스에서 정의됩니다.

콜백 중첩을 피하기 위해 요청한 값에 따라 함수 스택을 작동하도록 스케줄러를 작성했습니다. 스케줄러는 스택에서 함수를 꺼내 실행합니다. 함수의 콜백은 스택이 지워질 때까지 마지막에 스케줄러를 다시 호출합니다. 각 콜백은 원격 유효성 검사 호출에서 반환된 모든 유효성 검사 오류를 기록합니다.

내가 쓴 글은 안티 패턴인 것 같아요. Angular의 $http 호출에서 제공되는 약속을 사용하면 전체 확인 프로세스 동안 내 생각은 동기 프로그래밍처럼 더 선형적이 될 것입니다. 평면화된 약속 체인을 읽을 수 있습니다. 계속...

Promise 사용

큐 약속 라이브러리가 사용됩니다. Q 라이브러리에도 동일하게 적용됩니다. 라이브러리를 사용하려면 먼저 npm을 사용하여 kew 라이브러리를 NodeJS로 가져온 다음 코드를 NodeJS REPL에 로드하세요.

그림

'use strict';
var Q = require('kew');
var i = 0;
 
function log(data) {console.log('%d %s', ++i, data); };
 
// Asynchronous fn returns a promise
function async(arg) {
  var deferred = Q.defer();
  setTimeout(function () {
    deferred.resolve('result ' + arg);\
  }, 1000);
  return deferred.promise;
};
 
// Flattened promise chain
function validate() {
  log("Wait for it ...");
  async('first').then(function(resp){
    log(resp);
    return async('second');
  })
  .then(function(resp){
    log(resp);
    return async('third')
  })
  .then(function(resp){
    log(resp);
    return async('fourth');
  })
  .then(function(resp){
    log(resp);
  }).fail(log);
};
validate();

출력은 중첩된 콜백을 사용할 때와 동일합니다.

$ node scripts/examp2-pflat.js
1 Wait for it ...
2 result first
3 result second
4 result third
5 result fourth
$

该代码稍微“长高”了,但我认为更易于理解和修改。更易于加上适当的错误处理。在链的末尾调用fail用于捕获链中错误,但我也可以在任何一个then里面提供一个reject的处理函数做相应的处理。

服务器 或 浏览器

Promises在浏览器中就像在NodeJS服务器中一样有效。下面的地址, http://jsfiddle.net/mauget/DnQDx/,指向JSFiddle的一个展示如何使用一个promise的web页面。 JSFiddle所有的代码是可修改的。我故意操作随意动作。你可以试几次得到相反的结果。它是可以直接扩展到多个promise链, 就像前面NodeJS例子。

2015624113608681.jpg (572×265)

并行 Promises

考虑一个异步操作喂养另一个异步操作。让后者包括三个并行异步行为,反过来,喂最后一个行动。只有当所有平行的子请求通过才能通过。这是灵感来自偶遇一打MongoDB操作。有些是合格的并行操作。我实现了promises的流流程图。

2015624113731418.jpg (454×366)

我们怎么会模拟那些在该图中心行的并行promises?关键是,最大的promise库有一个全功能,它产生一个包含一组子promises的父promie。当所有的子promises通过,父promise通过。如果有一个子promise拒绝,父promise拒绝。
 

让十个并行的promises每个都包含一个文字promise。只有当十个子类通过或如果任何子类拒绝,最后的then方法才能完成。

Figure
 

var promiseVals = ['To ', 'be, ', 'or ',
  'not ', 'to ', 'be, ', 'that ',
  'is ', 'the ', 'question.'];
 
var startParallelActions = function (){
  var promises = [];
 
  // Make an asynchronous action from each literal
  promiseVals.forEach(function(value){
    promises.push(makeAPromise(value));
  });
 
  // Consolidate all promises into a promise of promises
  return Q.all(promises);
};
 
startParallelActions ().then( . . .

下面的地址, http://jsfiddle.net/mauget/XKCy2/,针对JSFiddle在浏览器中运行十个并行promises,随机的拒绝或通过。这里有完整的代码用于检查和变化if条件。重新运行,直到你得到一个相反的完成。2015624114246516.png (554×370)

孕育 Promise

许多api返回的promise都有一个then函数——他们是thenable。通常我只是通过then处理thenable函数的结果。然而,$q,mpromise,和kew库拥有同样的API用于创建,拒绝,或者通过promise。这里有API文档链接到每个库的引用部分。我通常不需要构造一个promise,除了本文中的包装promise的未知描述和timeout函数。请参考哪些我创建的promises。

Promise库互操作

大多数JavaScript promise库在then级别进行互操作。你可以从一个外部的promise创建一个promise,因为promise可以包装任何类型的值。then可以支持跨库工作。除了then,其他的promise函数则可能不同。如果你需要一个你的库不包含的函数,你可以将一个基于你的库的promise包装到一个新的,基于含有你所需函数的库创建的promise里面。例如,JQuery的promise有时为人所诟病。那么你可以将其包装到Q,$q,mpromise,或者kew库的promise中进行操作。
 
结语

现在我写了这篇文章,而一年前我却是犹豫要不要拥抱promise的那个。我只是单纯地想完成一项工作。 我不想学习新的API,或是打破我原来的代码(因为误解了promise)。我曾经如此错误地认为!当我下了一点注时,就轻易就赢得了可喜的成果。

在这篇文章中,我已经简单给出了一个单一的promise,promise链,和一个并行的promise的promise的的例子。 Promises不难使用。如果我可以使用它们,任何人都可以。 要查看完整的概念,我支持你点击专家写的参考指南。从Promises/A 的参考开始,从事实上的标准JavaScript的Promise 开始。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.