2016-09-11 4 views
0

Я новичок в мире node.js и Javascript, и у меня есть цикл, который перебирает массив объектов при определенном условии Мне нужно вызвать функцию что делает asnyc работы и петли для остановки в то время как функция не выполняетсяmake for loop wait for function to stop in node.js

fucntion foo1(arr){ 
    for(var i=0 ; arr.length>i ; i++){ 
     if(i==8){//or any other condition 
      doAsyncStuff(hits[i])    
     } 
    } 
} 

function doAsyncStuff(item){ 
parser.parseURL(someurl,function(error,result){ 
    item.someprop=result.someprop; 
}) 
} 

проблема не будет, независимо от того, что я делаю, я не могу показаться, чтобы сделать функцию ждать его конца, прежде чем у меня есть результат и не обновляет элемент, который мне нужен для обновления. Я понимаю, что это обычная проблема, но ни одно из решений, которые я нашел, не работал. Любая помощь будет приветствоваться. Спасибо!

+0

Читайте о 'async' библиотеке .... – Rayon

+0

обратного вызова, обещание, rxjs, асинхронный/Await. Любой из них поможет вам в этом случае. Но только последний позволит вам действительно создать цикл 'for' – smnbbrv

+0

Не очень-то, но у вас есть опечатка: fucntion – Tom

ответ

1

Зацикливание и создание асинхронного материала немного сложнее в JS. Вы можете использовать одну из библиотек, которые @smnbbrv упоминает в своем комментарии. Но вы также можете сделать это сами, что поможет вам понять, как работают некоторые из этих библиотек.

function foo1(arr) { 
    next(arr, 0) 
} 

function doAsyncStuff(item, cb) { 
    parser.parseURL(someurl, function(error, result) { 
    item.someprop = result.someprop; 
    cb(result); 
    }) 
} 

function next(arr, i) { 
    // Stop when we reach the end of the array. 
    if (i >= arr.length) { 
    return; 
    } 

    if (i == 8) { // or any condition 
    // Move to the next item only when the async work is done. 
    doAsyncStuff(arr[i], function() { 
     next(arr, i + 1) 
    }) 
    } else { 
    next(arr, i + 1) 
    } 
} 
0

Если я вас правильно понял, то вы могли бы использовать Promise цепь, сериализован используя reducefor цикл будет также работать), что-то вроде этого

function doAsyncStuff(item) { 
 
    return new Promise(resolve => { 
 
    const time = Math.ceil(Math.random() * 2000 + 1000); 
 
    window.setTimeout(() => { 
 
     item.someprop = time; 
 
     resolve(); 
 
    }, time); 
 
    }); 
 
} 
 

 
function foo1(arr) { 
 
    return arr.reduce(
 
    (promise, item, index) => index % 2 === 0 ? promise.then(() => doAsyncStuff(item)) : promise, 
 
    Promise.resolve() 
 
); 
 
} 
 

 
const hits = new Array(9).fill().map(() => ({})); 
 
foo1(hits).then(() => { 
 
    console.log(hits); 
 
});

Существует также Promise.all, который вы, вероятно, могли бы использовать (хотя и не уверен, как это было бы замечательно, я не часто встречаюсь с пользователем Promise).

Update: Использование Promise.all

function doAsyncStuff(item) { 
 
    return new Promise(resolve => { 
 
    const time = Math.ceil(Math.random() * 2000 + 1000); 
 
    window.setTimeout(() => { 
 
     item.someprop = time; 
 
     resolve(); 
 
    }, time); 
 
    }); 
 
} 
 

 
function foo1(arr) { 
 
    return Promise.all(
 
    arr.map((item, index) => index % 2 === 0 && doAsyncStuff(item)) 
 
); 
 
} 
 

 
const hits = new Array(9).fill().map(() => ({})); 
 
foo1(hits).then(() => { 
 
    console.log(hits); 
 
});

Я до сих пор не понял, что лучший способ форматирования ES6, всегда кажется, в конечном итоге с удлиненных линий. (вопрос личного стиля) :)

0

Я бы использовал обещания Bluebird и рисунок редуктора.

var Promise = require('bluebird'); 

// iterates over the array 'arr' and calls fn 
// Myfn repeatedly, optionally passing an initial. 
// for the 1st iteration. For subsequent iterations, 
// the value returned by prev invocation of Myfn is passed.  
Promise.reduce(arr, Myfn, someInitialValue); 

function Myfn(prev, item) { 
    //return a value or a promise. 
} 

см документации Уменьшить здесь: http://bluebirdjs.com/docs/api/promise.reduce.html