Javascript 顺序运行Q承诺

Javascript 顺序运行Q承诺,javascript,node.js,promise,q,Javascript,Node.js,Promise,Q,在Node.js应用程序中,我想实现以下目标: 根据项目类型读取数组,决定使用返回QPromise对象的特定函数。我希望此进程按顺序运行 我有两个承诺: var q = require('q'); Classes.prototype.fn1 = function (item) { return q.Promise(function(resolve, reject){ Items.find({item_published: true}).exec(

Node.js
应用程序中,我想实现以下目标: 根据项目类型读取数组,决定使用返回
Q
Promise
对象的特定函数。我希望此进程按顺序运行

我有两个承诺:

var q = require('q');
Classes.prototype.fn1 = function (item) {
    return q.Promise(function(resolve, reject){
        Items.find({item_published: true}).exec(
            function (err, events) {
                if (err) {
                    reject('an error happened');
                    throw err;
                }else{
                    resolve(events);
                }
        });
    });
};

Classes.prototype.fn2 = function (item) {
    return q.Promise(function(resolve, reject){
        resolve(item);
    });
};
这是主要代码:

self.items = [{},{},{}]; //some items
self.result = [];

self.items.forEach(function(item,index,array){

    if(item.type == 1){
        self.fn1(item)
            .then(function(result){
                self.result.push(result);
        })
    }

    if(item.type == 2){
        self.fn2(item)
            .then(function(result){
                self.result.push(result);
        })
    }

    if(index == array.length-1){
        callback(self.result);
     }
});

但它不起作用。因为
fn1
有一个异步进程,所以它在
fn2
之后运行。我只想按顺序运行这些函数,即使其中一个函数有异步进程。

您可以使用
.reduce
来链接承诺

var promise = q(); // Create a Resolved promise for chaining.
self.items = [{},{},{}]; //some items
self.result = [];

// We put an resolved promise as init value for chaining
self.items.reduce(function(chain, item) {
    // Don't do anything if item type is not match
    if (item.type !== 1 && item.type !== 2) {
      return chain;
    }

    var targetFunc = null;
    if (item.type === 1) {
      targetFunc = self.fn1;
    } else if (item.type === 2) {
      targetFunc = self.fn2;
    }

    if (targetFunc === null) {
      return chain;
    }

    // Chain the promise and return the last of the chain.
    return chain
      .then(function(){
        return targetFunc(item);
      })
      .then(function(result){
        // This then will get the result from above
        // so we put the result to self.result here
        self.result.push(result);
      });
}, promise).then(function() {
  // When all promises are sequentially resolved,
  // call the callback with self.resul.
  callback(self.result);
});

,。

您可以使用
.reduce
来链接承诺

var promise = q(); // Create a Resolved promise for chaining.
self.items = [{},{},{}]; //some items
self.result = [];

// We put an resolved promise as init value for chaining
self.items.reduce(function(chain, item) {
    // Don't do anything if item type is not match
    if (item.type !== 1 && item.type !== 2) {
      return chain;
    }

    var targetFunc = null;
    if (item.type === 1) {
      targetFunc = self.fn1;
    } else if (item.type === 2) {
      targetFunc = self.fn2;
    }

    if (targetFunc === null) {
      return chain;
    }

    // Chain the promise and return the last of the chain.
    return chain
      .then(function(){
        return targetFunc(item);
      })
      .then(function(result){
        // This then will get the result from above
        // so we put the result to self.result here
        self.result.push(result);
      });
}, promise).then(function() {
  // When all promises are sequentially resolved,
  // call the callback with self.resul.
  callback(self.result);
});

,.

与下面的烹饪非常相似。。。但是fuyushimoya的速度太快了,尽管我们处理reduce的初始化方式不同

var promises = self.items.map( function(item) {
    if (item.type == 2) {
      return self.fn1(item);
    }
    else if (item.type == 3) {
      return self.fn2(item);
    }
 });

function handler(p) {
  return p.then( function(res) {
    self.result.push(res);
  });
}

promises
 .reduce( function(prev, current) {
  if (prev) {
    return prev.then( function() { handler(current) } )
  } 
  else {
    return handler(current)
  }
})
 .then(function(result) {
    callback(null, result);
  })
  .catch( // error handler);

和下面的烹饪非常相似。。。但是fuyushimoya的速度太快了,尽管我们处理reduce的初始化方式不同

var promises = self.items.map( function(item) {
    if (item.type == 2) {
      return self.fn1(item);
    }
    else if (item.type == 3) {
      return self.fn2(item);
    }
 });

function handler(p) {
  return p.then( function(res) {
    self.result.push(res);
  });
}

promises
 .reduce( function(prev, current) {
  if (prev) {
    return prev.then( function() { handler(current) } )
  } 
  else {
    return handler(current)
  }
})
 .then(function(result) {
    callback(null, result);
  })
  .catch( // error handler);

把它画出来。但像这样的事情可能会奏效

UPD:诀窍是链接承诺,正如在评论中提到的,有一个更新版本,我用于:


把它画出来。但像这样的事情可能会奏效

UPD:诀窍是链接承诺,正如在评论中提到的,有一个更新版本,我用于:



不要拒绝和抛弃,只是拒绝。你为什么不把承诺连在一起呢?您还可以将
if
语句放在
then
方法中。@Minister:我尝试了很多方法,但最后,由于fn1的异步行为,没有遵循顺序。你能给我一个你所说的真实例子吗?有两天我解决不了这个问题。谢谢不要拒绝和抛弃,只是拒绝。你为什么不把承诺连锁反应呢?您还可以将
if
语句放在
then
方法中。@Minister:我尝试了很多方法,但最后,由于fn1的异步行为,没有遵循顺序。你能给我一个你所说的真实例子吗?有两天我解决不了这个问题。感谢您的解决方案非常紧凑,看起来很合理,但它不起作用。我不知道为什么。你能再检查一下吗?除了回调(self.result)外,一切正常;返回[]我找到了原因,最后一个master.then(function()在内部之前运行,然后可能需要将数据推送到arrayRegular循环而不是forEach。让我放置真实的代码示例并运行它。您的解决方案非常紧凑,似乎合理,但不起作用。我不知道原因。您能再次检查它吗?除了回调(self.result)之外,一切都正常;returns[]我找到了原因,最后一个master.then(function()在内部之前运行,然后可能需要将数据推送到arrayRegular循环而不是forEach。让我放置真实的代码示例并运行它。Reduce需要一个返回值。当前
var chained
什么都不做。它应该是
return chain。然后(…)
.Ah,我将return改为var是出于某种忘记的目的,但也忘了返回,非常感谢。@fuyushimoya:一切都很好,但最终self.result包含了我想要的重复值。事实上,我想要两个结果,但结果不止两个。你能再检查一遍吗?你在
self.items中输入了两个以上的值吗>?就像在你的原始帖子中一样,它包含3项。或者会有
item。键入
而不是1或2项,你不想处理它们。@fuyushimoya:如果我有两项,self.result.push(result);调用了4次!但是为什么?Reduce需要一个返回值。当前
var chained
什么都不做。它应该是
return chain。然后(…)
.Ah,我将return改为var是出于某种忘记的目的,但也忘了返回,非常感谢。@fuyushimoya:一切都很好,但最终self.result包含了我想要的重复值。事实上,我想要两个结果,但结果不止两个。你能再检查一遍吗?你在
self.items中输入了两个以上的值吗>?就像在你的原始帖子中一样,它包含3个项目。或者会有
项目。键入
而不是1或2,你不想处理它们。@fuyushimoya:如果我有两个项目,self.result.push(result);调用了4次!但是为什么?