2016-11-23 2 views
0

Я использую функцию javascript для получения другого сообщения для каждого элемента списка. Поэтому я использую функцию forEach, и я ищу way для выполнения функции callbackcb(result), когда foreach как закончен, так и завершается .forEach и msgAfterTimeout. Я читал, что было что-то по имени promises, но я действительно не понимаю, как я могу использовать их здесь.Array.forEach Обратный звонок в конце

function msgAfterTimeout (who, timeout, onDone) { 
    setTimeout(function() { 
     onDone(" Hello " + who + "!"); 
    }, timeout); 
} 
var test=""; 
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}]; 

function dispName(cb) 
{ 
    list.forEach(function(item, index) 
    { 
     msgAfterTimeout(item.name, 200, function (msg) 
     { 
      test=msg+"\n"; 

     }); 
     cb(result); 

    }); 

} 

dispName(function(data){ 
    console.log(data); 
}); 
+0

Что должно содержать результат? Он не определен выше. – Joe

ответ

0

Вот ваш пример с Promises:

var list = [{name: "foo", surname: "bar"}, {name: "Jean", surname: "dupond"}]; 
 

 

 
function msgAfterTimeout(who, timeout) { 
 
    return new Promise(resolve => 
 
     setTimeout(
 
      () => resolve(" Hello " + who + "!"), 
 
      timeout) 
 
    ); 
 
} 
 

 

 
Promise.all(
 
    list.map(item => msgAfterTimeout(item.name, 200)) 
 
).then(
 
    result => console.log(result.join('\n')) 
 
);

Ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

+0

Точно, что я искал спасибо – Yokida

0
function msgAfterTimeout (who, timeout, onDone) { 
    setTimeout(function() { 
     onDone(" Hello " + who + "!"); 
    }, timeout); 
} 

var test= ""; 
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}]; 

function newFunc(list, i, endCb) { 
    var name = list[i].name; 
    msgAfterTimeout(name, 200, function(msg) { 
      var test = msg + "\n"; 
      console.log(test); 
      if(i+1 == list.length) { 
       endCb(); 
      } 
      else { 
      newFunc(list, i+1, endCb); 
      } 
    }); 
} 

function dispName(cb) 
{ 
     newFunc(list, 0 , cb);  
} 

dispName(function(){ 
    console.log("Done with all!"); 
}); 

Это выходы:

Здравствуйте Foo! Привет, Джин! Готово со всеми!

0

forEach процессы вещей в серии, так что ради этого ответа, давайте предположим, это требование. Promise.all, как продемонстрировал @georg, обработает элементы в parallel - это хороший ответ, но это не поможет вам, если серия - это то, что вам действительно нужно.

Методы Array.prototype reduce, map и forEach являются синхронными, но вы можете легко сделать асинхронные варианты. Вы используете forEach здесь, но вы на самом деле выполняете reduce вручную. Итак, начнем с внедрения асинхронного reducek, а затем оттуда

Не беспокойтесь о понимании reducek. Все, что вам нужно знать, - это основное различие между и reduce в том, что функция уменьшения получает дополнительный аргумент обратного вызова, который вызывается, когда каждый элемент выполнен, а reducek имеет свой собственный обратный вызов, когда выполняется весь список ввода. не

function reducek (f, acc, [x, ...xs], k) { 
 
    if (x === undefined) 
 
    return k (acc) 
 
    else 
 
    return f (acc, x, y => reducek (f, y, xs, k)) 
 
} 
 

 
function msgAfterTimeout (who, timeout, onDone) { 
 
    return setTimeout(onDone, timeout, "Hello " + who + "!") 
 
} 
 

 
function messageReducer (acc, item, done) { 
 
    return msgAfterTimeout(item.name, 200, function (text) { 
 
    return done([...acc, text]) 
 
    }) 
 
} 
 

 
function displayName (list, done) { 
 
    // use our async reduce here 
 
    return reducek (messageReducer, [], list, done) 
 
} 
 

 
var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}] 
 

 
displayName (list, function (texts) { 
 
    console.log("Done!", texts.join(' ')) 
 
}) 
 

 
// Done! Hello foo! Hello Jean!

Важные вещи, чтобы заметить ...

  1. больше не выполняет уменьшить вручную - вместо того, чтобы использовать переменную test инициализирована с состоянием '' (пустая строка), reducek принимает начальное значение в качестве аргумента.

  2. Здесь мы используем начальное состояние [] (пустой массив) для хранения каждого из текстов. Когда мы закончим, мы объединяем тексты вместе, используя texts.join(' ').


Not Another церемонии ...

Все, что есть много церемонии и продолжения не обязательно являются лучшими для контроля асинхронного потока. Фактически, обещания были доведены до JavaScript, потому что нужен был лучший инструмент.

// instead of returning a timeout, return a Promise 
function msgAfterTimeout (who, timeout) { 
    return new Promise(function (resolve) { 
    setTimeout(resolve, timeout, "Hello " + who + "!") 
    }) 
} 

// new async/await syntax - work with Promises in a most elegant fashion 
// no more callback parameter; async implicitly returns a Promise 
async function displayName (list) { 
    let texts = [] 
    for (let item of list) 
    texts.push(await msgAfterTimeout(item.name, 200)) 
    return texts 
} 

var list = [{name:"foo",surname:"bar"},{name:"Jean",surname:"dupond"}] 

// instead of a callback, chain a .then on the returned Promise 
displayName(list).then(texts => console.log("Done!", texts.join(' '))) 

// Done! Hello foo! Hello Jean!

Примечание: Если вам необходимо поддерживать старые браузеры, async/await потребности быть transpiled, используя что-то вроде Бабеля.

Смежные вопросы