javascript ES6动态链接承诺

时间:2015-09-12 21:16:46

标签: javascript node.js ecmascript-6 es6-promise

我试图动态链接promises,以便处理需要按顺序发生的未知数量的异步调用。我使用IO.JS / chrome本机支持Promise。

承诺的创建立即触发(至少相对于控制台输出)。我期待能够收集承诺然后传递给Promise.all,但到那时他们已经因为我不理解的原因而被解雇了。

这是一种链接方法,由对Dynamic Chaining in Javascript Promises

的评论建议
            var lastPr = null;
            console.log(" exit setup......................");
            while(this.statesToExit.length > 0) {


                var v = this.statesToExit.shift();
                console.log("new Promise...");
                var pr = new Promise(function (resolve, reject) {

                    console.log("doing Exit stuff at time " +curTime); 
                    resolve();  //SOMETHING MORE SUBSTANTIAL GOES HERE

                });

                console.log("lastPr.then.");
               if (lastPr != null) {
                    lastPr.then(pr);
                }
                lastPr = pr;
              //  console.log("adding pr to worklist");
               // promiseList.push(pr);
                // });
            }

另一种方法是

            var promiseList= [];
            console.log(" exit setup......................");
            while(this.statesToExit.length > 0) {


                var v = this.statesToExit.shift();
                console.log("new Promise...");
                var pr = new Promise(function (resolve, reject) {

                    console.log("doing Exit stuff at time " +curTime); 
                    resolve();  //SOMETHING MORE SUBSTANTIAL GOES HERE

                });

                console.log("adding pr to worklist");
                promiseList.push(pr);
                 });
            }
 console.log("Transition *START*-" +promiseList.length +" ");
       Promise.all(promiseList).catch(function(error) {
            console.log("Part of TransitionCursor Failed!", error);
        }).then(this.summarizeWorkDone());

在这两种情况下,输出都是

new Promise...
doing Exit stuff at time 0
new Promise...
doing Exit stuff at time 0
    "Transition *START*-"

与预期的

相对应
new Promise...
new Promise...
    "Transition *START*-"
doing Exit stuff at time 0
doing Exit stuff at time 0

如何动态创建承诺列表以便以后执行?

3 个答案:

答案 0 :(得分:0)

确定,

所以人们都在投票给我答案因为我提供了外部链接,这实际上是我写的。好难过!所以修改答案和之前的答案都在这个答案的底部。

在这里,我将重点介绍第一个例子中的问题,因为这是我在本文底部链接中解释的内容。

首先:你没有链接承诺,而是创造了多个承诺。创建promise时,会立即调用传递给构造函数的函数。有关详细信息,请查看以下链接中教程的第1部分。这就是为什么你在“新承诺”行之后得到输出行“按时退出东西......”。你没有对curTime说什么,但看起来这些值并不正确,尽管这不是这篇文章的重点。

其次,您应该将lastPr.then()分配给lastPr(),但是您要将新创建的pr分配给lastPr。这在以下链接的第2部分进行了解释。

第三,我会说你的预期输出说我应该提醒你,传递给promise构造函数的函数会立即启动。所以你不应该在创建promise期间打印任何东西,而是在then()方法中将它们推下来。但是,我在这里没有这样做,所以你会看到第一个'在0时间做退出的东西'行出现在第一个'新Promise ...'行之后。

第四,你没有显示'lastPr.then'。在预期产出

注意:我更改了代码的curTime和statesToExit(删除了'this'引用并分配了测试数组)

我会建议这样的事情:

var curTime = 0;
var lastPr = null;
console.log(" exit setup......................");
var statesToExit = [1, 2, 3]; // NOTE: the change to make this code runnable.
while (statesToExit.length > 0) {
    var v = statesToExit.shift();
    console.log("new Promise...");

    if (lastPr == null) {
        lastPr = new Promise(function (resolve, reject) {
            console.log("doing Exit stuff at time " + curTime);
            resolve();  //SOMETHING MORE SUBSTANTIAL GOES HERE
        });
    }
    else {

        console.log("lastPr.then."); // NOTE: This does not appear in your expected output
        lastPr = lastPr.then(result => {
            console.log("doing Exit stuff at time " + curTime);
            return Promise.resolve();  //SOMETHING MORE SUBSTANTIAL GOES HERE
        });
    }
    //  console.log("adding pr to worklist");
    // promiseList.push(pr);
    // });
}

// NOTE: now you need to esecute the chain:
// you should handle promise rejection:
// check the tutorial link:
// https://github.com/tuhinpaul/syp-model/wiki/Programmatic-Chaining-and-Recursive-Functions-with-JavaScript-Promise
lastPr.catch(err => { console.log(err); });

以上代码的输出:

 exit setup......................
new Promise...
doing Exit stuff at time 0
new Promise...
lastPr.then.
new Promise...
lastPr.then.
doing Exit stuff at time 0
doing Exit stuff at time 0

我在以下教程中描述了动态承诺链:检查以下教程

  1. javascript / node.js promises和
  2. 的程序化(动态)链接
  3. 使用递归函数保证链接
  4. Programmatic-Chaining-and-Recursive-Functions-with-JavaScript-Promise

答案 1 :(得分:-1)

我对Promises的理解确实没有,正如这个优秀的页面所提到的那样:http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html首先他们立即开始执行,其次要动态地执行你必须使用工厂函数来推迟执行:

首先创建连锁开始。

    var chain = Promise.resolve();
   //     chain.then(this.doTranStart);

然后对于每个状态(数组),然后创建一个代理闭包,以便可以使用适当的数据回调该函数。我不确定javascript中是否有内置的东西,所以我从actionscript 2.0中移植了一个库,当它遇到类似的问题时就回来了。

    this.statesToExit.forEach(function (state) {
            console.log("new Exit Promise Chain...");
              var pxfn = GetProxy.getProxy(self, self.doExitFactory, [curTime,state._fn,state]);
               chain = chain.then(pxfn);
            });

然后运行工厂链,然后调用工厂然后执行承诺。

chain.catch(function(error) {
            console.log("Part of TransitionCursor Failed!", error);
        }).then(this.summarizeWorkDone);

第一个是工厂方法,非常简单。

   doExitFactory(curTime,fn,stateScope) {
        console.log("doExitFactory " );//+ curTime,fn,stateScope );
        return this.doExit(curTime,fn,stateScope);
    }

这是完成工作的实际功能。在给定范围内动态调用函数。

    doExit(curTime, _fn, stateScope) {
        console.log("doExit");
        return new Promise(function (resolve, reject) {   
          //  console.log("doing actual Exit stuff at time ");//+ curTime);
            _fn.apply(stateScope, [{sig: STATE.EXIT}, resolve, reject]);
            resolve();

        })
    }

输出看起来像

TransitionCursor.setRoute
starting to create chain
new Exit Promise Chain...
new Exit Promise Chain...
finishing create chain


calling chain to start............
Transition *START*--------------------------
doExitFactory 
doExit
IS_s11 (EXIT)
doExitFactory 
doExit
IS_s1 (EXIT)
summarizeWorkDone:--------------- 

其中IS_s11和IS_s1是我想按顺序运行的实际异步函数。

答案 2 :(得分:-1)

您写道:

new Promise((r)=>r()).then(new Promise((r)=>r());

你想写什么:

new Promise((r)=>r()).then(()=>new Promise((r)=>r()));

要使您的代码按照您想要的方式工作,请更改

lastPr.then(pr);

lastPr.then(()=>pr);