2017-01-31 3 views
0

jquery에서 deffered ajax에 $ .when을 사용하면 몇 가지 단점이있었습니다. Ajax 호출이 성공적으로 처리되면 좋습니다. 그러나 하나가 실패하면 다른 요청에서 다른 데이터를 가져올 수 없습니다.

Ex.

 

    var ajax1Success = function() { 
     return $.ajax(...); 
    }; 

    var ajax2Success = function() { 
     return $.ajax(...); 
    }; 

    var ajax3BoundtoFail = function() { 
     return $.ajax(...); 
    }; 


    $.when(ajax1Succes(), ajax2Success(), ajax3BoundtoFail()).done(function(a1, a2, a3) { 
     // all good 

    }).fail(function() { 
     // not good... ajax3 is bound to fail 
    }); 

좋은 해결책 어떻게 성공했는지 아약스 요청에서 다른 데이터를 가져 오는 방법은 무엇입니까?

답변

1

$.when()은 "빠른 패스트"디자인을가집니다. 즉, 첫 번째 약속이 실패하면 $.when()이 거부되고 거부 정보 만 나타납니다. jQuery 문서에서 :

The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected

그러나 약속 유형을 모니터링하는 데는 다른 유형의 기능을 사용할 수 있습니다. 이러한 유형의 기능은 모든 약속이 확정 될 때까지 기다리고 해결되거나 거절 되더라도 모든 결과를 얻는 "결재"라고도합니다.

다음은 다음과 같이 사용할 수 있습니다 내가 과거에 사용했던의 jQuery promies에 대한 이러한 구현의 :

$.settle([ajax1Succes(), ajax2Success(), ajax3BoundtoFail()]).then(function(results) { 
    // results is an array of PromiseInspection Objects 
    // for each of them, you can see if the corresponding promise 
    // succeeded with a value or failed with an error 
    results.forEach(function(pi, index) { 
     if (pi.isFulfilled()) { 
      console.log("Promise #" + (index + 1) + " succeeded with result " + pi.value()); 
     } else { 
      console.log("Promise #" + (index + 1) + " failed with reason " + pi.reason()); 
     } 
    }); 
}); 

또는 조금 더 간단한 버전을 사용하면 정확한 오류가 필요하지 않은 경우가 :

$.settleVal(null, [ajax1Succes(), ajax2Success(), ajax3BoundtoFail()]).then(function(results) { 
    // results contains the results from all the successful promises 
    // any promises that has an error will show null as the result 
}); 

주, 이들은 그들이 약속의 배열을이 현실 세계에서 사용하기 일반적으로 쉽게 경향으로 결과의 배열에 해결 표준 Promise.all()처럼 많은 인터페이스를 사용합니다.

그리고, 여기에 구현의 :

(function() {  

    function isPromise(p) { 
     return p && (typeof p === "object" || typeof p === "function") && typeof p.then === "function"; 
    } 

    function wrapInPromise(p) { 
     if (!isPromise(p)) { 
      p = $.Deferred().resolve(p); 
     } 
     return p; 
    } 

    function PromiseInspection(fulfilled, val) { 
     return { 
      isFulfilled: function() { 
       return fulfilled; 
      }, isRejected: function() { 
       return !fulfilled; 
      }, isPending: function() { 
       // PromiseInspection objects created here are never pending 
       return false; 
      }, value: function() { 
       if (!fulfilled) { 
        throw new Error("Can't call .value() on a promise that is not fulfilled"); 
       } 
       return val; 
      }, reason: function() { 
       if (fulfilled) { 
        throw new Error("Can't call .reason() on a promise that is fulfilled"); 
       } 
       return val; 
      } 
     }; 
    } 

    // pass either multiple promises as separate arguments or an array of promises 
    $.settle = function(p1) { 
     var args; 
     if (Array.isArray(p1)) { 
       args = p1; 
     } else { 
      args = Array.prototype.slice.call(arguments); 
     } 

     return $.when.apply($, args.map(function(p) { 
      // make sure p is a promise (it could be just a value) 
      p = wrapInPromise(p); 
      // Now we know for sure that p is a promise 
      // Make sure that the returned promise here is always resolved with a PromiseInspection object, never rejected 
      return p.then(function(val) { 
       return new PromiseInspection(true, val); 
      }, function(reason) { 
       // convert rejected promise into resolved promise by returning a resolved promised 
       // One could just return the promiseInspection object directly if jQuery was 
       // Promise spec compliant, but jQuery 1.x and 2.x are not so we have to take this extra step 
       return wrapInPromise(new PromiseInspection(false, reason)); 
      }); 
     })).then(function() { 
       // return an array of results which is just more convenient to work with 
       // than the separate arguments that $.when() would normally return 
      return Array.prototype.slice.call(arguments); 
     }); 
    } 

    // simpler version that just converts any failed promises 
    // to a resolved value of what is passed in, so the caller can just skip 
    // any of those values in the returned values array 
    // Typically, the caller would pass in null or 0 or an empty object 
    $.settleVal = function(errorVal, p1) { 
     var args; 
     if (Array.isArray(p1)) { 
       args = p1; 
     } else { 
      args = Array.prototype.slice.call(arguments, 1); 
     } 
     return $.when.apply($, args.map(function(p) { 
      p = wrapInPromise(p); 
      return p.then(null, function(err) { 
       return wrapInPromise(errorVal); 
      }); 
     })); 
    } 
})();