如何使用这种模式将RSVP承诺设置为可链接的闭包装?

时间:2015-05-09 01:38:03

标签: javascript promise deferred rsvp.js

我想接受RSVP全局对象,并将其包装到我的全局应用程序闭包中的闭包中,这样我就可以按照我想要的方式调用它。它还使我更容易记住如何使用它,以后在开发中。

以下是一些背景知识:RSVP librarya promise tutorial using it

所以给定RSVP的这个标准用法:

new RSVP.Promise(function(resolve, reject) {
  // succeed
  resolve(value);
  // or reject
  reject(error);
});

如何使用您在下面看到的设计模式为此创建包装器?我想把这个RSVP对象放到包装器中,这样我就不必每次都在同一个地方实例化一个新的RSVP Promise并定义我的回调。

我希望每次想要做出新的承诺时,只需致电var newPromise = app.core.promise(callback)

如何将它包装成一个闭包以便可能?这就是我到目前为止 - 正确的方法是什么?

app.core.promise = function (resolveFunc, paramObj) {

    if(typeof(resolveFunc) === 'function'){

        //lets move on shall we?
        return new window.RSVP.Promise(function(resolveFunc, reject){

            //so this is the real question, what am i to do here?
            if(paramObj){
                //do something with this object first, or just run it, depending on your use case
                //paramObj = chopBalls(paramObj);
                resolveFunc(paramObj);
            } else {
                resolveFunc();
            }
            reject(error);
        });
    }
};

我意识到这样做几乎没有理由,但看看我将它们链接在下面的很酷的方式 - 我认为这是值得的。

然后我可以在下面做这个来制作链条,我认为这对我需要的东西来说更清洁,这将是很棒的,这是我的目标!

var chain1, chain2;

    chain1 = app.core.promise(someSuccesCallback);

    chain1.then(function(){
        nowDoAChain1Operation();
    }) ;

    chain1.then(function(){
        nowFollowupOnChain1();
    }) ;

    chain1.catch(function(error){
        throw "we DO have an exception my friends in Chain1.  This is the master catch for the chain1.  Error object:" + error;    
    });

    chain2 = app.core.promise(aChain2OperationFunction);

    chain2.then(function(){
        anotherChain2Function();
    }) ;

    chain2.catch(function(error){
        throw "we DO have an exception my friends, in Chin2!  This is a master catch for the chain2.  Error object:" + error;
    });

它看起来很熟悉吗?这是标准延迟的使用方式,这是我试图模仿的方式,因为我已经使用标准的jQuery Deferreds一段时间了,并取得了巨大的成功。

app.core.promise = function(){
    return $.Deferred();  //ajax call promise
};

我是否有可能在不打败目的的情况下做什么? (这是我为应用程序选择的设计模式。设计模式是否有意义?)。

编辑代码更新@Benjamin,

所以我想在这里发布我的更改,看看这是否正确。请注意我如何在这里做最后3次返回。这在所有情况下都是必要的吗?不对?它只取决于你在最后一次返回后是否需要承诺,或者响应完成了吗?或者,总是需要返回?即使在render方法中推出了自己的html响应?这是例如代码..

    //app.core.js
app.core.promise = function () {
    //lets move on shall we?
    return window.RSVP.Promise.resolve();
};

//app.ui.js
app.ui.showAmazonResults = function(){

    var promiseChain = app.core.promise(); //setup the promise

    promiseChain = promiseChain.then(function(){
        return app.ui.getSelectedIds(); //this runs a static function that might have a slow iteration
    });

    promiseChain = promiseChain.then(function(ids){
        app.ui.selectedIds = ids;  //just sets up a final property needed by the next call. 
        return app.convertData(); //this guy finishes the processing and setting up all the needed data fore the next call.
    });

    promiseChain = promiseChain.then(function(data){
        //all properties are clean and ready to be posted, run the 3rd party call..
        return app.amazon.fetchApi(); //this guy runs an api call out to a 3rd party
    });

    promiseChain = promiseChain.then( function(amazonData){
        //app.amazon.renderData(amazonData); //important to pass in null page here, so the dashboard and old results doesn't disappear on showing more results
        return app.amazon.renderData(amazonData); // this guy just renders this up front as rendered html, to the view.  so i dont know it needs to be returned
    });

    promiseChain = promiseChain.catch(function(errorResponse){
        //app.helper.log(errorResponse, 'myPage.this_ajax_call');
        return app.helper.log(errorResponse, 'myPage.this_ajax_call');
    });

    return promiseChain; //this entire methods jobs is to completly process and do the dirty work for the cals above, and also renders, so i dont know that this eitehr needs to be returned, since its parent may not need this converted to a promise.  or does it for whatever reason?
};

//somewhere inside an onready or init, where events are setup for the app all you need is after a user checks off items, then the following is ran on submit..  

app.ui.showAmazonResults();   

这就是我使用它的方式。

1 个答案:

答案 0 :(得分:5)

嗯,承诺都是关于返回值

当你这样做时:

chain1.then(function(){
    nowFollowupOnChain1();
});

你没有将承诺链接起来而不是等待nowFollowupOnChain1内的操作 - 相反,你正在分支链。您可能想要做的是使用返回值并将承诺链接起来:

chain1 = chain1.then(function(){
    return nowFollowupOnChain1();
});

现在,任何then chain1的{​​{1}}将等待操作首先完成。这是链接点。您通常应该convert whatever callback API you're using to return promises,然后从那时起很少调用promise构造函数。完成后you can enjoy chaining which will take care of most of those issues for you

如果您想在RSVP中创建一个空的已解决的承诺,您可以随时调用RSVP.Promise.resolve(),这将返回一个结算RSVP承诺。您也可以像RSVP.defer()一样在jQuery中执行$.Deferred(),但我强烈建议您$.Deferred sort of misses the point of promises以后反对它。

另外,请考虑不要扔弦,它们不会有堆叠痕迹,会让你的生活变得非常困难:)