2016-03-15 6 views
1

Нажатие на стену здесь, пытаясь заставить это работать - вывод console.log должен быть 0, 1, 2, 3. Он должен в основном цикл по массиву и вызов функции в последовательности неблокируемого способа (ожидание done(), если он принят в):Петля через асинхронные обратные вызовы в неблокирующей последовательности

var array = [ 

    function(done) { 
    setTimeout(function() { 
     console.log(0); 
     done(); 
    }, 2000); 
    }, 

    function(done) { 
    setTimeout(function() { 
     console.log(1); 
     done(); 
    }, 200); 
    }, 

    function() { 
    // This one is synchronous and doesn't need 
    // to use done() 
    console.log(2); 
    }, 

    function(done) { 
    setTimeout(function() { 
     console.log(3); 
     done(); 
    }, 70); 
    } 

]; 

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

function fnWrapper(fn) { 
    return new Promise(function(resolve) { 
    if (fn.length >= 1) { 
     // If the done callback is passed in. 
     fn(resolve); 
    } else { 
     fn(); 
     resolve(); 
    } 
    }); 
} 

array.reduce((promise, fn) => promise.then(fnWrapper(fn)), Promise.resolve()); 

http://codepen.io/ferahl/pen/wGoRZN?editors=0010

Но до сих пор мои попытки перебрать это с генератором или пообещать/уменьшить очень сломана. Есть идеи? Благодарю.

Update: PS Я не могу контролировать то, что асинхронный метод будет использоваться для вызова done() в

ответ

0

Я понял, что для того, чтобы мои обещания выполнялись последовательно, мне нужно было вернуть функцию, которая вернула обещание в then (вместо того, чтобы передавать в нее обещание):

function fnWrapper(fn) { 
    return new Promise(function(resolve) { 
    if (fn.length >= 1) { 
     // If the done callback is passed in. 
     fn(resolve); 
    } else { 
     fn(); 
     resolve(); 
    } 
    }); 
} 

array.reduce((promise, fn) => promise.then(() => fnWrapper(fn)), Promise.resolve()); 

Codepen: http://codepen.io/ferahl/pen/wGoRZN?editors=0010

3

Вот решение, используя обещания (и Array.prototype.reduce для выполнения функций в серии):

// promise version of setTimeout 
function delay(ms) { 
    return new Promise((resolve) => { 
    setTimeout(resolve, ms); 
    }); 
} 

var array = [ 
    function() { 
    return delay(2000) 
     .then(() => console.log(0)); 
    }, 

    function() { 
    return delay(200) 
     .then(() => console.log(1)); 
    }, 

    function() { 
    console.log(2); 
    }, 

    function() { 
    return delay(70) 
     .then(() => console.log(3)); 
    } 
]; 

array.reduce((promise, fn) => promise.then(fn), Promise.resolve()); 

CodePen

+0

Это прекрасное решение спасибо, проблема заключается в том, что эти функции написаны пользователями, и я не могу контролировать то, что асинхронный метод они используют –

+0

ли метод асинхронного ожидается быть последовательным? Лучше всего выбрать метод и объяснить своим пользователям, какой метод асинхронного API ожидает. – SimpleJ

+0

Да, возможно, вы правы, я дам ему подумать и принять, если я не могу придумать что-то. –