簡體   English   中英

Javascript Prom遞歸和鏈接

[英]Javascript promise recursion and chaining

我應該如何編寫遞歸循環以正確地順序執行promise? 我已經嘗試過Promise.all(Array.map(function(){})); 這不符合我的需求,因為這些步驟需要按順序執行。 我在這里找到了一個自定義的Promise,但是它也有問題。

承諾:

var promiseFor = (function(condition, action, value) {
    var promise = new Promise(function(resolve, reject) {
        if(!condition(value)) {
            return;
        }
        return action(value).then(promiseFor.bind(null, condition, action));
    });
    return promise;
});

此問題的原因在於,它似乎在最深的遞歸調用處停止,而不返回繼續執行循環以正確完成。

例如:在PHP中這樣的代碼:

function loopThrough($source) {
    foreach($source as $value) {
        if($value == "single") {
            //do action
        } else if($value == "array") {
            loopThrough($value);
        }
    }
}

如果我通過一個文件夾結構,“單個”表示文件,它將打印所有文件。 但是我使用的承諾在第一個死角就停止了。

編輯:添加了藍鳥,看看它是否可以幫助任何事情,還是一樣。 這是當前的循環代碼

var runSequence = (function(sequence, params) { 
    return Promise.each(sequence, function(action) {
        console.log(action['Rusiavimas'] + ' - ' + action['Veiksmas']);
        if(params.ButtonIndex && params.ButtonIndex != action['ButtonIndex']) {
            return Promise.resolve();
        }

        if(action['Veiksmas'].charAt(0) == '@') {
            var act = action['Veiksmas'];
            var actName = act.substr(0, act.indexOf(':')).trim();
            var actArg = act.substr(act.indexOf(':')+1).trim();

            /* This one is the code that figures out what to do and
               also calls this function to execute a sub-sequence. */
            return executeAction(actName, actArg, params);
        } else {
            sendRequest('runQuery', action['Veiksmas']);
        }
    });
});

我有3個序列,每個序列包含5個動作。 第一個和第二個序列具有下一個序列,這是它的第三個動作。 這是我得到的結果(數字表示順序):

1 - @PirmasVeiksmas
1 - @AntrasVeiksmas
1 - @Veiksmas: list_two
2 - @PirmasVeiksmas
2 - @AntrasVeiksmas
2 - @Veiksmas: list_three
3 - @PirmasVeiksmas
3 - @AntrasVeiksmas
3 - @TreciasVeiksmas
3 - @KetvirtasVeiksmas
3 - @PenktasVeiksmas

如您所見,它進入下一個序列並按原樣繼續,但是一旦第三個序列完成,它應該恢復第二個序列並以第一個序列結束。 但是一旦到達遞歸的第一個死胡同,它就會停止。

EDIT2:我現在擁有的Codepen示例以及發生的事情的可視化表示: Codepen鏈接

輸出應為:

fa1
second
sa1
third
ta1
ta2
ta3
sa3
fa3

可以使用.reduce()而不是.map()來按順序運行一堆動作。

這是一個例子:

 // Helper function that creates a Promise that resolves after a second const delay = (value) => new Promise(resolve => setTimeout(() => resolve(value), 1000)); const arr = [1, 2, 3, 4, 5]; // concurrent resolution with `.map()` and `Promise.all()` Promise.all(arr.map(delay)) .then(console.log.bind(console)); // [1, 2, 3, 4, 5] after a second. // sequential resolution with `.reduce()` arr.reduce((promise, current) => promise .then(() => delay(current)) .then(console.log.bind(console)), Promise.resolve()); // second wait, 1, second wait, 2... 

如果我正確理解了您的需求,那么您就不需要Promise遞歸,這只是您發現順序運行Promises的方式。 .reduce()可以更輕松地幫助您。

簡化過程將[1,2,3,4,5]轉換為:

Promise.resolve()
  .then(() => delay(1))
  .then(console.log.bind(console))
  .then(() => delay(2))
  .then(console.log.bind(console))
  .then(() => delay(3))
  .then(console.log.bind(console))
  .then(() => delay(4))
  .then(console.log.bind(console))
  .then(() => delay(5))
  .then(console.log.bind(console))

請注意,如果要訪問所有結果,則需要做更多的工作。 但我會將其留給讀者練習:)

因此,這可以解決代碼筆代碼的問題,從而提供所需的輸出。

var sequences = {
  first: ['fa1', 'second', 'fa3'],
  second: ['sa1', 'third', 'sa3'],
  third: ['ta1', 'ta2', 'ta3']
};

var loopThrough = (function(sequence) {
  return sequence.forEach(function(action) {
    return doAction(action);
  });
});

var doAction = (function(action) {
  var promise = new Promise(function(resolve, reject) {
    console.log(action);
    if(action == 'second' || action == 'third') {
      //recurse into sub-sequence
      return loopThrough(sequences[action]);
    } else {
      //do something here
    }
    resolve();
  });
  return promise;
});

loopThrough(sequences.first);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM