문제

내 질문은 약속의 우아한 병렬화에 관한 것입니다. 블루버드 Promise를 구축하는 함수에 컨텍스트와 인수를 모두 전달해야 할 때.

내 문제를 이해하고 테스트할 수 있도록 만들기 위해 종속성이 없는 예제를 만들었습니다.

내가 계산을 한다고 가정해보자( 1/(x엑스x) + 1/(x*x) ) 비동기 "컴퓨터"(리소스가 해제되어야 함)와 관련됩니다.정사각형과 정육면체는 비동기적이고 독립적으로 계산됩니다.

다음과 같이 계산을 수행할 수 있습니다.

InitComputer(2) // returns a promise
.then(invert)
.then(function(arg){
    return Promise.all([
        proto.square(arg),
        proto.cube(arg)
    ]);
}).spread(function(sq, cu){
    this.set(sq + cu);
}).catch(function(err){
    console.log('err:', err);
}).finally(endComputer);

하지만 나는 이 사용법을 발견했습니다. all 이론적으로 가능한 것에 비해 너무 무겁습니다.함수를 인수로 전달할 때 then, 실행되었습니다.함수를 전달할 때 all, 그렇지 않습니다. 오류가 있습니다.유틸리티나 패턴이 누락된 것 같습니다.

이 스타일에서 더 간단한 것으로 변경하는 솔루션이 있습니까?

InitComputer(2)
.then(invert)
.all([
    proto.square,
    proto.cube
]).spread(function(sq, cu){
    this.set(sq + cu);
}).catch(function(err){
    console.log('err:', err);
}).finally(endComputer);

?

아마 해킹할 수도 있겠지 Promise.prototype.all 또는 다형성 증가를 피하기 위해 새 함수를 정의하지만 나는 내가 소유하지 않은 개체의 수정과 관련되지 않은 솔루션에만 관심이 있습니다.


신관:

내 테스트에서 "컴퓨터"를 정의하는 방법은 다음과 같습니다.

var Promise = require("bluebird");

function Computer(){}
function InitComputer(v){
    // initializing a computer is asynchronous and may fail hence the promise
    var c = new Computer(), resolver = Promise.defer();
    setTimeout(function(){
        if (v>1) resolver.resolve(v);
        else resolver.reject(new Error("bad value: "+v));
    },100);
    return resolver.promise.bind(c);
}
var proto = Computer.prototype;
proto.square = function(x){
    // imagine this really uses the computer and is asynchronous
    if (!this instanceof Computer) throw new Error('not a computer');
    return x*x
}
proto.cube = function(x){ return x*x*x }
proto.set = function(v){ this.value = v }

function endComputer(){
    // releases resources here
    console.log('value:', this.value);
}

// this asynchronous function doesn't involve or know the computer
function invert(v){ return 1/v }
도움이 되었습니까?

해결책

Promise.all를 사용할 필요가 없습니다.수행하는 대신 :

.then(function(arg){
    return Promise.all([
        proto.square(arg),
        proto.cube(arg)
    ]);
}).spread(...
.

단순히 사용할 수 있습니다 :

.then(function(arg){
    return [proto.square(arg), proto.cube(arg)];
}).spread(...
.

node.js에서 화살표 기능이 있으면 다음과 같이 간단합니다.

.then(arg => [proto.square(arg), proto.cube(arg)]).spread(...
.

Promise.all는 적어도 2 개의 약속이 적어도 약속의 사슬을 시작 에 사용하는 경우에 사용됩니다.예 :

var promise1 = somePromise();
var promise2 = somePromise2();

// Start the chain here
Promise.all([promise1, promise2])
.spread(function(value1, value2) {
    // ...
});
.

다른 팁

귀하가 언급한 것과 같은 리소스 사용 사례 관리를 위해 블루버드는 Promise.using(). Promise.using() 설정할 수 있습니다 disposer() 사용을 마쳤을 때 비동기적으로 검색된 리소스를 자동으로 닫는 함수

Promise.join() 결과를 결합하는 데도 도움이 될 것입니다. cube 그리고 square 비동기 방식

여기서 나는 당신을 약간 다시 썼습니다 InitComputer 이것이 어떻게 작동하는지 설명하는 예 - 이제 Computer val 대신에 속성으로 val이 추가된 인스턴스를 배치했습니다. endComputer 프로토에서도

메모:당신은 항상 사용할 수 있습니다 Promise.method() 이렇게 하면 지연된 결과를 반환하는 대신 다음과 같습니다.

var invert = Promise.method(function invert(v){ return 1/v })

새로운 초기화컴퓨터:

function InitComputer(v){
    var c = new Computer(), resolver = Promise.defer();
    setTimeout(function(){
        if (v>1) {
            c.val = v;
            resolver.resolve(c);
        }
        else resolver.reject(new Error("bad value: "+v));
    },100); /** notice resource disposer function added below **/
    return resolver.promise.bind(c).disposer(function(compu){compu.endComputer()});
}

새 코드:

Promise.using(InitComputer(1.2), function(computer){
    return invert(computer.val)
    .then(function(inverted){
        return Promise.join(computer.square(inverted), computer.cube(inverted), 
            function(sq, cu){
                computer.set(sq + cu)
            }
        )
    })
    .catch(function(err){
        console.log('err:', err);
    });
})
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top