2017-10-18 141 views
1

我正在使用具有不带回调方法的node.js模块。取而代之的是,当该方法完成时会触发事件。我想解决一个承诺,使用该事件作为回调确保我的方法已成功完成。等待事件以解决承诺

array.lenght在承诺可以是X.所以,我需要'听'X次事件,以确保所有方法已成功完成< - 这不是问题,我只是告诉你,我知道这可能发生

事件:

tf2.on('craftingComplete', function(recipe, itemsGained){ 
    if(recipe == -1){ 
    console.log('CRAFT FAILED') 
    } 
    else{ 
     countOfCraft++; 
    console.log('Craft completed! Got a new Item #'+itemsGained); 
    } 
}) 

承诺:

const craftWepsByClass = function(array, heroClass){ 
     return new Promise(function (resolve, reject){ 

      if(array.length < 2){ 
       console.log('Done crafting weps of '+heroClass); 
       return resolve(); 
      } 
      else{ 
       for (var i = 0; i < array.length; i+=2) { 
        tf2.craft([array[i].id, array[i+1].id]); // <--- this is the module method witouth callback 
       } 
     return resolve(); // <---- I want resolve this, when all tf2.craft() has been completed. I need 'hear' event many times as array.length 
      } 

     }) 
} 
+0

'tf2.craft()'是否返回'Promise'?请注意,一个'Promise'只能解决或拒绝一次。 – guest271314

+0

@ guest271314不要。 tf2.craft()不返回任何内容; –

+0

'有一个没有回调的方法.''很好''是一个回调.. :) – Keith

回答

0

起初让promisify工艺加工:

function craft(elem){ 
//do whatever 
return Promise((resolve,reject) => 
    tf2.on('craftingComplete', (recipe,itemsGained) => 
    if(recipe !== -1){ 
    resolve(recipe, itemsGained); 
    }else{ 
    reject("unsuccessful"); 
    } 
    }) 
); 
} 

所以到工艺倍数那么,我们我们的阵图,以承诺和使用Promise.all:

Promise.all(array.map(craft)) 
.then(_=>"all done!") 
+0

'resolve'和'reject'从哪里来?它们看起来并不在范围内。 – Bergi

+0

@Bergi你有没有休息日。?解决和拒绝是在承诺回调.. – Keith

+1

@凯斯'承诺'执行器功能不包括在原代码 – guest271314

-1

我需要检查,如果事件'craftingComplete'已经发射了很多次,当我呼叫tf2.craft时,我的号码为 。对任何可能的身份证件或手艺失败都没有影响。 我需要知道,如果tf2.craft已完成,仅为什么检查 “craftingComplete”事件

既然我们知道ifor循环将递增i += 2其中i小于.lengtharray,我们可以在for循环之前创建等于该数字的变量和事件处理

const craftWepsByClass = function(array, heroClass) { 
    return new Promise(function(resolve, reject) { 

    var countCraft = 0; 
    var j = 0; 
    var n = 0; 
    for (; n < array.length; n += 2); 

    tf2.on('craftingComplete', function(recipe, itemsGained) { 
     if (recipe == -1) { 
     console.log('CRAFT FAILED') 
     } else { 
     countOfCraft++; 
     console.log('Craft completed! Got a new Item #' + itemsGained); 
     if (j === n) { 
      resolve(["complete", craftCount]) 
     } 
     } 
    }) 

    if (array.length < 2) { 
     console.log('Done crafting weps of ' + heroClass); 
     return resolve(); 
    } else { 
     try { 
     for (var i = 0; i < array.length; i += 2, j += 2) { 
      tf2.craft([array[i].id, array[i + 1].id]); 
     } 
     } catch (err) { 
     console.error("catch", err); 
     throw err 
     } 
    } 

    }) 
} 

craftWepsByClass(array, heroClass) 
.then(function(data) { 
    console.log(data[0], data[1]) 
}) 
.catch(function(err) { 
    console.error(".catch", err) 
}) 
+0

我不认为每次调用'craftWepsByClass'时都要添加一个新的'craftingComplete'处理函数。 – Bergi

+0

@Bergi可能不是。 'craftWepsByClass()'只对每个新的'tf2'实例调用一次。 OP现在有几种可能的解决方案可供选择。 – guest271314

+0

“*'craftWepsByClass()'只对每个新的'tf2'实例调用一次*” - 你怎么知道这个的?为什么你甚至认为有多个'tf2'实例? – Bergi

0

内比较i的数字。如果事件将在相同的订单,被解雇s表示导致他们各自craft()调用,您可以使用一个队列:

var queue = []; // for the tf2 instance 
function getNextTf2Event() { 
    return new Promise(resolve => { 
    queue.push(resolve); 
    }); 
} 
tf2.on('craftingComplete', function(recipe, itemsGained) { 
    var resolve = queue.shift(); 
    if (recipe == -1) { 
    resolve(Promise.reject(new Error('CRAFT FAILED'))); 
    } else { 
    resolve(itemsGained); 
    } 
}); 

function craftWepsByClass(array, heroClass) { 
    var promises = []; 
    for (var i = 1; i < array.length; i += 2) { 
    promises.push(getNextTf2Event().then(itemsGained => { 
     console.log('Craft completed! Got a new Item #'+itemsGained); 
     // return itemsGained; 
    })); 
    tf2.craft([array[i-1].id, array[i].id]); 
    } 
    return Promise.all(promises).then(allItemsGained => { 
    console.log('Done crafting weps of '+heroClass); 
    return …; 
    }); 
} 

如果你不知道事件的顺序任何东西,可以有多个并发调用craftWepsByClass,你无法避免全球计数器(即一个链接到tf2实例)。缺点是例如在两个重叠的电话a = craftWepsByClass(…), b = craftWepsByClass()中,a承诺在第二个电话完成后才能解决。

var waiting = []; // for the tf2 instance 
var runningCraftings = 0; 
tf2.on('craftingComplete', function(recipe, itemsGained) { 
    if (--runningCraftings == 0) { 
    for (var resolve of waiting) { 
     resolve(); 
    } 
    waiting.length = 0; 
    } 
    if (recipe == -1) { 
    console.log('CRAFT FAILED') 
    } else { 
    console.log('Craft completed! Got a new Item #'+itemsGained); 
    } 
}); 

function craftWepsByClass(array, heroClass) { 
    for (var i = 1; i < array.length; i += 2) { 
    runningCraftings++; 
    tf2.craft([array[i-1].id, array[i].id]); 
    } 
    return (runningCraftings == 0 
    ? Promise.resolve() 
    : new Promise(resolve => { 
     waiting.push(resolve); 
     }) 
).then(() => { 
    console.log('Done crafting weps of '+heroClass); 
    }); 
} 

当然,在这两种解决方案,你必须是100%肯定的是,每次调用craft()原因只有一个事件。

+0

良好的捕获,不应该有任何。 – Bergi