> 웹 프론트엔드 > JS 튜토리얼 > JavaScript에서 Promise 사용

JavaScript에서 Promise 사용

高洛峰
풀어 주다: 2018-05-15 17:35:36
원래의
1350명이 탐색했습니다.

Promise는 비동기 작업에 대한 콜백 함수를 처리하는 방법을 표준화하는 ES6의 함수입니다. 해당 기능은 jQuery의 deferred와 유사합니다. 간단히 말해서, Promise 객체의 다양한 상태를 통해 다양한 콜백 함수가 호출됩니다. 현재 IE8 이하는 지원되지 않지만, 다른 브라우저는 지원됩니다.

Pending에서 Resolved 또는 Rejected로 변환된 후에도 Promise 개체의 상태는 변경되지 않습니다.

사용 단계:

var promise = new Promise(function(resolve, reject) {

 // 异步任务,通过调用resolve(value) 或 reject(error),以改变promise对象的状态;改变状态的方法只能在此调用。

//promise状态改变后,会调用对应的回调方法

});

promise.then(function(value){//resolve时的回调函数,参数由异步的函数传进来})

.catch(function(error){//发生异常时或明确reject()时的回调函数})
로그인 후 복사

구체적인 사용법:

function getURL(URL) {           //因为promise创建时即执行,所以用工厂函数封装promise对象
  return new Promise(function (resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', URL, true);
    req.onload = function () {
      if (req.status === 200) {
        resolve(req.responseText);
      } else {
        reject(new Error(req.statusText));
      }
    };
    req.onerror = function () {
      reject(new Error(req.statusText));
    };
    req.send();
  });
}
// 运行示例
var URL = "http://httpbin.org/get";
getURL(URL).then(function onFulfilled(value){
  console.log(value);
}).catch(function onRejected(error){
  console.error(error);
})
로그인 후 복사

Promise의 콜백은 비동기식일 뿐이며 동기 작업의 콜백도 비동기적으로 실행됩니다.

var promise = new Promise(function (resolve){
  console.log("inner promise");         // 执行1:同步任务先执行
  resolve(‘callBack');
});
promise.then(function(value){
  console.log(value);              // 执行3:虽然注册时状态为resolved,但回调仍是异步的;
});
console.log("outer promise");          // 执行2:同步代码先执行
로그인 후 복사

Promise의 메소드 체인

then 메소드에 등록된 콜백이 순차적으로 호출되며, 반환값을 통해 각 then 메소드 사이에 매개변수가 전달됩니다. 그러나 콜백의 예외로 인해 then 콜백을 건너뛰고 catch 콜백이 직접 호출된 다음 나머지 then 콜백이 호출됩니다. then(onFulfilled, onRejected)에서는 onFulfilled 예외가 자체 onRejected에 의해 포착되지 않으므로 catch가 먼저 사용됩니다.

promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask);

taskA에서 예외가 발생하고 taskB는 건너뛰고 finalTask는 계속 유지됩니다. catch에 의해 반환된 Promise 개체의 상태가 확인되었기 때문에 호출되었습니다.

then 메소드에서는 세 가지 값을 반환할 수 있습니다.

1. 또 다른 promise 객체를 반환합니다. 다음 then 메소드는 상태에 따라 실행할 onFullfilled/onRejected 콜백 함수를 선택합니다. /reject 메서드 전달에 따라 결정됩니다.

2. 다음 then 메서드는 현재 Promise 개체의 상태를 상속하고 기다리지 않고 즉시 실행됩니다. 종료할 비동기 작업; 실제 매개변수는 이전의 반환 값입니다. 반환되지 않으면 기본적으로 정의되지 않은 상태를 반환합니다.

3. 예외 발생(동기/비동기): throw new Error('xxx) ');

그런 다음 콜백 함수를 등록할 뿐만 아니라 콜백 함수의 반환 값을 변환하여 새로운 Promise 객체를 생성하고 반환합니다. 실제로 Promise는 메소드 체인의 동일한 Promise 객체에서 작동하지 않습니다.

var aPromise = new Promise(function (resolve) {
  resolve(100);
});
var thenPromise = aPromise.then(function (value) {
  console.log(value);
});
var catchPromise = thenPromise.catch(function (error) {
  console.error(error);
});
console.log(aPromise !== thenPromise); // => true
console.log(thenPromise !== catchPromise);// => true
로그인 후 복사

Promise.all() 정적 메서드는 동시에 여러 비동기 작업을 수행합니다. 후속 처리는 수신된 모든 Promise 객체가 FulFilled 또는 Rejected가 될 때까지 계속되지 않습니다.

Promise.all([promiseA, promiseB]).then(function(results){//results是个数组,元素值和前面promises对象对应});

// 由promise对象组成的数组会同时执行,而不是一个一个顺序执行,开始时间基本相同。
function timerPromisefy(delay) {
  console.log('开始时间:”'+Date.now()) 
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(delay);
    }, delay);
  });
}
var startDate = Date.now();
Promise.all([
  timerPromisefy(100),    //promise用工厂形式包装一下
  timerPromisefy(200),
  timerPromisefy(300),
  timerPromisefy(400)
]).then(function (values) {
  console.log(values);  // [100,200,300,400]
});
로그인 후 복사

는 동시에 실행되지 않고 차례로 실행됩니다. promise

//promise factories返回promise对象,只有当前异步任务结束时才执行下一个then
function sequentialize(promiseFactories) {
  var chain = Promise.resolve();
  promiseFactories.forEach(function (promiseFactory) {
    chain = chain.then(promiseFactory);
  });
  return chain;
}
로그인 후 복사

Promise.race()는 all()과 유사하지만 race()에는 하나의 promise만 필요합니다. 개체를 FulFilled 또는 Rejected 상태로 전환하면 해당 콜백 함수가 실행됩니다. 그러나 첫 번째 Promise 객체가 Fulfilled가 된 후에는 다른 Promise 객체의 지속적인 실행에 영향을 미치지 않습니다.

//沿用Promise.all()的例子
Promise.race([
  timerPromisefy(1),
  timerPromisefy(32),
  timerPromisefy(64),
  timerPromisefy(128)
]).then(function (value) {
  console.log(values);  // [1]
});
로그인 후 복사

Promise.race()를 타이머로 활용하는 멋진 방법

Promise.race([
  new Promise(function (resolve, reject) {
    setTimeout(reject, 5000);     // timeout after 5 secs
  }),
  doSomethingThatMayTakeAwhile()
]);
로그인 후 복사

Then에서 Promise 상태 변경

Then의 콜백에는 값 매개변수만 있기 때문입니다. , 상태를 변경할 수 있는 방법이 없습니다(생성자의 비동기 작업에서만 사용할 수 있음). 다음으로 전달된 Promise 객체의 상태를 변경하려면 새 Promise 객체를 생성하고 결정하면 됩니다. 비동기 작업의 상태를 변경하고 마지막으로 다음 then/catch를 반환할지 여부입니다.

var promise = Promise.resolve(‘xxx');//创建promise对象的简介方法
promise.then(function (value) {
  var pms=new Promise(function(resolve,reject){
    setTimeout(function () {
      // 在此可以判断是否改变状态reject/resolve
      Reject(‘args');
    }, 1000);
  })
  return pms;  //该promise对象可以具有新状态,下一个then/catch需要等异步结束才会执行回调;如果返回普通值/undefined,之后的then/catch会立即执行
}).catch(function (error) {
  // 被reject时调用
  console.log(error)
});
로그인 후 복사

두 Promise의 결과 가져오기

//方法1:通过在外层的变量传递
var user;
getUserByName('nolan').then(function (result) {
  user = result;
  return getUserAccountById(user.id);
}).then(function (userAccount) {
  //可以访问user和userAccount
});

//方法2:后一个then方法提到前一个回调中
getUserByName('nolan').then(function (user) {
  return getUserAccountById(user.id).then(function (userAccount) {
    //可以访问user和userAccount
  });
});
로그인 후 복사

Promise를 사용할 때 전체 구조에 주의하세요

doSomething()과 doSomethingElse()가 둘 다 Promise 객체를 반환한다고 가정합니다

일반적인 방법:

doSomething().then(doSomethingElse).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(resultOfDoSomething)  //返回新promise,下一个then要收到新状态才执行
         |------------------|
                   finalHandler(resultOfDoSomethingElse)
                   |---------------------|
로그인 후 복사

일반적인 해결 방법:

doSomething().then(function () { return doSomethingElse();}).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(undefined) //then外层函数的arguments[0]== resultOfDoSomething
         |------------------|
                   finalHandler(resultOfDoSomethingElse)
                   |------------------|
로그인 후 복사

잘못된 방법 1:

doSomething().then(function () { doSomethingElse();}).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(undefined)  //虽然doSomethingElse会返回promise对象,但最外层的回调函数是return undefined,所以下一个then方法无需等待新promise的状态,会马上执行回调。
         |------------------|
         finalHandler(undefined)
         |------------------|
로그인 후 복사

잘못된 방법 2:

doSomething().then(doSomethingElse()).then(finalHandler);
doSomething
|-----------------|
doSomethingElse(undefined)     //回调函数在注册时就直接被调用
|----------|
         finalHandler(resultOfDoSomething)
         |------------------|
로그인 후 복사

JavaScript의 추가 약속 PHP 사용과 관련된 기사는 PHP 중국어 웹사이트를 주목하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿