일련의 jQuery 연기로 어떻게 작업합니까?


132

루트 URL, 스키마 및 특정 순서로 데이터를로드 해야하는 응용 프로그램이 있습니다. 마지막으로 다양한 데이터 객체의 스키마와 URL로 응용 프로그램을 초기화하십시오. 사용자가 애플리케이션을 탐색 할 때 데이터 오브젝트가로드되고 스키마에 대해 유효성이 검증 된 후 표시됩니다. 사용자가 데이터를 CRUD 할 때 스키마는 1 차 유효성 검사를 제공합니다.

초기화에 문제가 있습니다. Ajax 호출을 사용하여 루트 객체 $ .when ()을 가져온 다음 각 스키마 객체마다 하나씩 약속 배열을 만듭니다. 작동합니다. 콘솔에 가져 오기가 표시됩니다.

그런 다음 모든 스키마에 대한 페치가 표시되므로 각 $ .ajax () 호출이 작동합니다. fetchschemas ()는 실제로 약속 배열을 반환합니다.

그러나 마지막 when () 절은 실행되지 않으며 "DONE"이라는 단어가 콘솔에 나타나지 않습니다. jquery-1.5의 소스 코드는 "null"이 $ .when.apply ()에 전달할 객체로 받아 들일 수 있음을 나타냅니다. 통과했다.

이것은 Futures.js를 사용하여 작동했습니다. 이 방법이 아닌 경우 jQuery Deferred 배열을 어떻게 관리해야합니까?

    var fetch_schemas, fetch_root;

    fetch_schemas = function(schema_urls) {
        var fetch_one = function(url) {
            return $.ajax({
                url: url,
                data: {},
                contentType: "application/json; charset=utf-8",
                dataType: "json"
            });
        };

        return $.map(schema_urls, fetch_one);
    };

    fetch_root = function() {
        return $.ajax({
            url: BASE_URL,
            data: {},
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    };

    $.when(fetch_root()).then(function(data) {
        var promises = fetch_schemas(data.schema_urls);
        $.when.apply(null, promises).then(function(schemas) {
            console.log("DONE", this, schemas);
        });
    });

"DONE"이 인쇄되기 전에 fetch_one의 각 ajax 쿼리에 대해 "성공"메소드를 실행해야한다는 점을 제외하고는 거의 동일한 문제가 있습니다. 어떻게하면 좋을까요? "fetch_one"다음에 .pipe를 사용하려고 시도했지만 작동하지 않는 것 같습니다.
CambridgeMike

답변:


198

당신이 찾고있는

$.when.apply($, promises).then(function(schemas) {
     console.log("DONE", this, schemas);
}, function(e) {
     console.log("My ajax failed");
});

이것은 또한 작동합니다 (일부 가치의 경우 깨진 아약스를 수정하지 않습니다).

$.when.apply($, promises).done(function() { ... }).fail(function() { ... });` 

inside 가를 참조 하도록 $대신 전달하려고 할 것입니다 . 소스에는 중요하지 않지만 전달하는 것이 좋습니다 .nullthis$.whenjQuerynull

모든 $ .ajax를 교체하고 $.when샘플 작업을 수행 하여 모의

따라서 그것은 아약스 요청의 문제이거나 fetch_schemas에 전달하는 배열입니다.


감사합니다. 이 구문은 done (). fail ()과 어떻게 다릅니 까?
Elf Sternberg

2
@elf Sternberg, .then(a,b) === .done(a).fail(b)게으른 속기입니다. .done(a).fail(b)원하는 경우 전화 할 수 있습니다
Raynos

1
아, 그리고 $ .when.apply ($, ...)와 $ .when.apply (null, ...)의 사용은 관련이없는 것 같습니다. jQuery 자체에는 promise () 메소드가 없으므로 내부적으로 생성 된 Deferred 객체 (jQuery 1.5, 943 행)를 위해 무시됩니다.
Elf Sternberg

1
@ ElfSternberg 그것은 실제로 관련이 없지만 가독성을 위해에 대해 한 눈에 살펴볼 필요는 없습니다 $.when.apply($, .... 는 null날 보내하게 "무엇 대기?". 스타일과 코딩 연습의 문제입니다. thisjQuery.when에서 null 참조를 throw하지 않을 것임을 확인하기 위해 소스를 읽어야했습니다 !
Raynos

7
null을 사용하면 '괜찮습니다. 이것은 일종의 해결 방법입니다'라고 생각합니다. $가 사용되면 내주의가 $에 대한 wtf에 대한 생각으로 바뀌 었습니다.
Danyal Aytekin

53

위의 해결 방법 (감사합니다!) 제대로의 연기에 제공되는 객체 돌아 가지의 문제를 해결하지 않는 resolve()jQuery를가 호출 때문에 방법 done()fail()각각의 매개 변수가 아닌 배열과 콜백을. 즉, arguments의사 배열 을 사용하여 지연된 배열에서 반환 된 모든 확인 / 거부 된 개체를 가져와야합니다.

$.when.apply($, promises).then(function() {
     var schemas=arguments; // The array of resolved objects as a pseudo-array
     ...
};

지연된 배열을 전달 했으므로 결과 배열을 다시 가져 오는 것이 좋습니다. 의사 배열 대신 실제 배열을 다시 가져 와서 같은 메소드를 사용할 수도 있습니다 Array.sort().

다음은 이러한 문제를 해결 하는 when.jswhen.all()방법에서 영감을 얻은 솔루션입니다 .

// Put somewhere in your scripting environment
if (jQuery.when.all===undefined) {
    jQuery.when.all = function(deferreds) {
        var deferred = new jQuery.Deferred();
        $.when.apply(jQuery, deferreds).then(
            function() {
                deferred.resolve(Array.prototype.slice.call(arguments));
            },
            function() {
                deferred.fail(Array.prototype.slice.call(arguments));
            });

        return deferred;
    }
}

이제 지연 / 프로 미스 배열을 전달하고 콜백에서 해결 / 거부 된 오브젝트 배열을 다음과 같이 다시 가져올 수 있습니다.

$.when.all(promises).then(function(schemas) {
     console.log("DONE", this, schemas); // 'schemas' is now an array
}, function(e) {
     console.log("My ajax failed");
});

@crispyduck-then ()의 "스키마"var에있는 배열 요소의 순서가 항상 "promises"var에있는 ajax 호출과 동일한 순서가 될 것임을 100 % 확신 할 수 있는지 아는가? ()?
netpoetica

6
이것은 jQuery에 내장되어야하지만 jQuery 팀은 요청을 여러 번 거부했습니다. 한편, 사람들은 여기에서 질문을 계속하고 jQuery에 대해 비슷한 티켓을 열고 우리는 모든 곳에서 사용자 랜드 구현 및 / 또는 어색한 호출을 apply()합니다.
mindplay.dk

이 솔루션에 감사드립니다! 하나 이상의 품목이 고장난 경우에도 성공적인 품목을 얻는 방법이 있습니까?
doktoreas

여기서 당신이 한 모든 arguments것은 자신의 방법으로 숨겨진 조작입니다. 다시 사용하기 위해 좋은,하지만 처리해야하는 "추"를 해결하지 않습니다이 arguments: (당신은 그냥 쉽게 할 수var schemas=Array.prototype.slice.call(arguments);)
cowbert

2
@ crispyduck, deferred.fail(...)읽어서는 안 deferred.reject(...)됩니까?
밥 S

19

ES6 버전의 자바 스크립트를 사용하는 경우 객체 배열을 쉼표로 구분 된 인수로 변환하는 스프레드 연산자 (...)가 있습니다.

$.when(...promises).then(function() {
 var schemas=arguments; 
};

ES6 스프레드 연산자에 대한 자세한 내용 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator here


1
예. Coffeescript 또는 그 자손 / 모방 자 중 하나를 사용하는 사람들은 지금 당장 그 운영자에게 접근 할 수있었습니다.
Elf Sternberg

0

이 코드로 확장 :

var rawWhen = $.when
$.when = function(promise) {
    if ($.isArray(promise)) {
        var dfd = new jQuery.Deferred()
        rawWhen.apply($, promise).done(function() {
            dfd.resolve(Array.prototype.slice.call(arguments))
        }).fail(function() {
            dfd.reject(Array.prototype.slice.call(arguments))
        })
        return dfd.promise()
    } else {
        return rawWhen.apply($, arguments)
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.