2017-10-18 138 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