IT story

약속을 차례로 (즉, 순서대로) 해결 하시겠습니까?

hot-time 2020. 4. 14. 19:15
반응형

약속을 차례로 (즉, 순서대로) 해결 하시겠습니까?


직렬 / 순차 방식으로 파일 배열을 읽는 다음 코드를 고려하십시오. readFiles모든 파일을 순서대로 읽은 후에 만 ​​해결되는 약속을 반환합니다.

var readFile = function(file) {
  ... // Returns a promise.
};

var readFiles = function(files) {
  return new Promise((resolve, reject) => 

    var readSequential = function(index) {
      if (index >= files.length) {
        resolve();
      } else {
        readFile(files[index]).then(function() {
          readSequential(index + 1);
        }).catch(reject);
      }
    };

   readSequential(0); // Start!

  });
};

위의 코드는 작동하지만 순차적으로 발생하기 위해 재귀를 수행하는 것을 좋아하지 않습니다. 이상한 readSequential기능 을 사용할 필요가 없도록이 코드를 다시 작성할 수있는 더 간단한 방법이 있습니까?

원래 나는을 사용하려고했지만 Promise.all모든 readFile호출이 동시에 발생했기 때문에 원하는 것이 아닙니다 .

var readFiles = function(files) {
  return Promise.all(files.map(function(file) {
    return readFile(file);
  }));
};

2017 업데이트 : 환경에서 지원하는 경우 비동기 기능을 사용합니다.

async function readFiles(files) {
  for(const file of files) {
    await readFile(file);
  }
};

원하는 경우 비동기 생성기를 사용하여 파일이 필요할 때까지 파일을 읽는 것을 연기 할 수 있습니다 (환경에서 지원하는 경우).

async function* readFiles(files) {
  for(const file of files) {
    yield await readFile(file);
  }
};

업데이트 : 다시 생각하면 for 루프를 대신 사용할 수 있습니다.

var readFiles = function(files) {
  var p = Promise.resolve(); // Q() in q

  files.forEach(file =>
      p = p.then(() => readFile(file)); 
  );
  return p;
};

또는 더 축소하여 다음을 수행하십시오.

var readFiles = function(files) {
  return files.reduce((p, file) => {
     return p.then(() => readFile(file));
  }, Promise.resolve()); // initial
};

다른 약속 라이브러리 (예 : Bluebird)에는이를위한 유틸리티 방법이 있습니다.

예를 들어, Bluebird는 다음과 같습니다.

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));

var readAll = Promise.resolve(files).map(fs.readFileAsync,{concurrency: 1 });
// if the order matters, you can use Promise.each instead and omit concurrency param

readAll.then(function(allFileContents){
    // do stuff to read files.
});

오늘날 async await를 사용 하지 않는 이유는 없습니다 .


다음은 일련의 작업을 선호하는 방법입니다.

function runSerial() {
    var that = this;
    // task1 is a function that returns a promise (and immediately starts executing)
    // task2 is a function that returns a promise (and immediately starts executing)
    return Promise.resolve()
        .then(function() {
            return that.task1();
        })
        .then(function() {
            return that.task2();
        })
        .then(function() {
            console.log(" ---- done ----");
        });
}

작업이 더 많은 사례는 어떻습니까? 10 살처럼?

function runSerial(tasks) {
  var result = Promise.resolve();
  tasks.forEach(task => {
    result = result.then(() => task());
  });
  return result;
}

이 질문은 오래되었지만 우리는 ES6와 기능적인 JavaScript의 세계에 살고 있으므로 개선 할 수있는 방법을 살펴 보겠습니다.

약속은 즉시 실행되므로 약속의 배열을 만들 수는 없으며 모두 동시에 시작됩니다.

대신 약속을 반환하는 함수 배열을 만들어야합니다. 그런 다음 각 기능이 순차적으로 실행되고 약속이 시작됩니다.

우리는 이것을 몇 가지 방법으로 해결할 수 있지만 가장 좋아하는 방법은을 사용하는 것입니다 reduce.

reduce약속과 함께 사용하면 약간 까다로워 지므로 하나의 라이너를 아래의 작은 소화 가능한 물기로 나눕니다.

이 함수의 본질은 reduce초기 값으로 시작 Promise.resolve([])하거나 빈 배열을 포함하는 약속을 사용하는 것입니다.

이 약속은 다음 reduce과 같은 방법으로 전달 됩니다 promise. 이것이 각 약속을 순차적으로 연결하는 열쇠입니다. 다음 실행 약속 functhen화재 발생시 결과가 연결되고 그 약속이 반환 reduce되어 다음 약속 기능으로 사이클을 실행합니다 .

모든 약속이 실행되면 반환 된 약속에는 각 약속의 모든 결과 배열이 포함됩니다.

ES6 예 (한 라이너)

/*
 * serial executes Promises sequentially.
 * @param {funcs} An array of funcs that return promises.
 * @example
 * const urls = ['/url1', '/url2', '/url3']
 * serial(urls.map(url => () => $.ajax(url)))
 *     .then(console.log.bind(console))
 */
const serial = funcs =>
    funcs.reduce((promise, func) =>
        promise.then(result => func().then(Array.prototype.concat.bind(result))), Promise.resolve([]))

ES6 예 (파손)

// broken down to for easier understanding

const concat = list => Array.prototype.concat.bind(list)
const promiseConcat = f => x => f().then(concat(x))
const promiseReduce = (acc, x) => acc.then(promiseConcat(x))
/*
 * serial executes Promises sequentially.
 * @param {funcs} An array of funcs that return promises.
 * @example
 * const urls = ['/url1', '/url2', '/url3']
 * serial(urls.map(url => () => $.ajax(url)))
 *     .then(console.log.bind(console))
 */
const serial = funcs => funcs.reduce(promiseReduce, Promise.resolve([]))

용법:

// first take your work
const urls = ['/url1', '/url2', '/url3', '/url4']

// next convert each item to a function that returns a promise
const funcs = urls.map(url => () => $.ajax(url))

// execute them serially
serial(funcs)
    .then(console.log.bind(console))

ES6에서 간단히 수행하려면 :

function(files) {
  // Create a new empty promise (don't do that with real people ;)
  var sequence = Promise.resolve();

  // Loop over each file, and add on a promise to the
  // end of the 'sequence' promise.
  files.forEach(file => {

    // Chain one computation onto the sequence
    sequence = 
      sequence
        .then(() => performComputation(file))
        .then(result => doSomething(result)); 
        // Resolves for each file, one at a time.

  })

  // This will resolve after the entire chain is resolved
  return sequence;
}

표준 Node.js 약속을위한 간단한 유틸리티 :

function sequence(tasks, fn) {
    return tasks.reduce((promise, task) => promise.then(() => fn(task)), Promise.resolve());
}

최신 정보

items-promise 는 NPM 패키지를 사용할 준비가되었습니다.


나는 많은 순차적 작업을 실행해야 했고이 답변을 사용하여 순차적 작업을 처리하는 기능을 위조했습니다 ...

function one_by_one(objects_array, iterator, callback) {
    var start_promise = objects_array.reduce(function (prom, object) {
        return prom.then(function () {
            return iterator(object);
        });
    }, Promise.resolve()); // initial
    if(callback){
        start_promise.then(callback);
    }else{
        return start_promise;
    }
}

이 함수는 2 개의 인수 + 1 개의 옵션을 취합니다. 첫 번째 주장은 우리가 작업 할 배열입니다. 두 번째 인수는 약속 자체를 반환하는 함수 인 작업 자체이며,이 약속이 해결 될 때만 다음 작업이 시작됩니다. 세 번째 인수는 모든 작업이 완료되었을 때 실행되는 콜백입니다. 콜백이 전달되지 않으면 함수는 생성 된 약속을 반환하여 끝을 처리 할 수 ​​있습니다.

사용 예는 다음과 같습니다.

var filenames = ['1.jpg','2.jpg','3.jpg'];
var resize_task = function(filename){
    //return promise of async resizing with filename
};
one_by_one(filenames,resize_task );

누군가 시간을 절약하기를 바랍니다.


내가 알아낼 수 있었던 가장 좋은 해결책은 bluebird약속이었습니다. Promise.resolve(files).each(fs.readFileAsync);약속이 순차적으로 해결되도록 보장 할 수 있습니다 .


이것은 위의 다른 답변의 약간의 변형입니다. 기본 약속 사용 :

function inSequence(tasks) {
    return tasks.reduce((p, task) => p.then(task), Promise.resolve())
}

설명

이러한 작업이있는 경우 [t1, t2, t3]위와 같습니다 Promise.resolve().then(t1).then(t2).then(t3). 축소 동작입니다.

사용하는 방법

먼저 작업 목록을 구성해야합니다! 작업은 인수를받지 않는 함수입니다. 함수에 인수를 전달해야하는 경우 bind또는 다른 방법을 사용하여 작업을 만듭니다. 예를 들면 다음과 같습니다.

var tasks = files.map(file => processFile.bind(null, file))
inSequence(tasks).then(...)

내가 선호하는 솔루션 :

function processArray(arr, fn) {
    return arr.reduce(
        (p, v) => p.then((a) => fn(v).then(r => a.concat([r]))),
        Promise.resolve([])
    );
}

여기에 출판 된 다른 것들과 근본적으로 다르지 않지만 :

  • 일련의 항목 기능을 적용합니다
  • 결과 배열로 해석
  • 비동기 / 대기 필요 없음 (2017 년경 지원은 여전히 ​​제한적 임)
  • 화살표 기능을 사용합니다. 좋고 간결한

사용법 예 :

const numbers = [0, 4, 20, 100];
const multiplyBy3 = (x) => new Promise(res => res(x * 3));

// Prints [ 0, 12, 60, 300 ]
processArray(numbers, multiplyBy3).then(console.log);

합리적인 최신 Chrome (v59) 및 NodeJS (v8.1.2)에서 테스트되었습니다.


를 사용 Array.prototype.reduce하고 약속을 함수로 감싸 야합니다. 그렇지 않으면 이미 실행중인 것입니다!

// array of Promise providers

const providers = [
  function(){
     return Promise.resolve(1);
  },
  function(){
     return Promise.resolve(2);
  },
  function(){
     return Promise.resolve(3);
  }
]


const inSeries = function(providers){

  const seed = Promise.resolve(null); 

  return providers.reduce(function(a,b){
      return a.then(b);
  }, seed);
};

좋고 쉬운 ... 당신은 성능 등을 위해 같은 시드를 재사용 할 수 있어야합니다

reduce를 사용할 때 빈 배열이나 요소가 하나 뿐인 배열지키는 것이 중요 하므로이 기술이 가장 좋습니다.

   const providers = [
      function(v){
         return Promise.resolve(v+1);
      },
      function(v){
         return Promise.resolve(v+2);
      },
      function(v){
         return Promise.resolve(v+3);
      }
    ]

    const inSeries = function(providers, initialVal){

        if(providers.length < 1){
            return Promise.resolve(null)
        }

        return providers.reduce((a,b) => a.then(b), providers.shift()(initialVal));
    };

그런 다음 다음과 같이 호출하십시오.

inSeries(providers, 1).then(v => {
   console.log(v);  // 7
});

Promise 객체에서이 간단한 방법을 만들었습니다.

Promise.sequence 메서드를 만들어 Promise 개체에 추가

Promise.sequence = function (chain) {
    var results = [];
    var entries = chain;
    if (entries.entries) entries = entries.entries();
    return new Promise(function (yes, no) {
        var next = function () {
            var entry = entries.next();
            if(entry.done) yes(results);
            else {
                results.push(entry.value[1]().then(next, function() { no(results); } ));
            }
        };
        next();
    });
};

용법:

var todo = [];

todo.push(firstPromise);
if (someCriterium) todo.push(optionalPromise);
todo.push(lastPromise);

// Invoking them
Promise.sequence(todo)
    .then(function(results) {}, function(results) {});

Promise 객체로의 확장에 대한 가장 좋은 점은 약속 스타일과 일치한다는 것입니다. Promise.all과 Promise.sequence는 같은 방식으로 호출되지만 의미가 다릅니다.

주의

순차적 인 약속 실행은 일반적으로 약속을 사용하는 좋은 방법이 아닙니다. 일반적으로 Promise.all을 사용하는 것이 좋으며 브라우저가 가능한 빨리 코드를 실행하도록하십시오. 그러나 자바 스크립트를 사용하여 모바일 앱을 작성할 때와 같은 실제 사용 사례가 있습니다.


promiseFactories List를 얻는이 기능을 사용할 수 있습니다.

function executeSequentially(promiseFactories) {
    var result = Promise.resolve();
    promiseFactories.forEach(function (promiseFactory) {
        result = result.then(promiseFactory);
    });
    return result;
}

Promise Factory는 Promise를 반환하는 간단한 함수입니다.

function myPromiseFactory() {
    return somethingThatCreatesAPromise();
}

약속 팩토리는 요청 될 때까지 약속을 만들지 않기 때문에 작동합니다. 당시 함수와 같은 방식으로 작동합니다. 실제로는 동일합니다!

당신은 약속의 배열을 전혀 조작하고 싶지 않습니다. 약속 사양에 따라 약속이 생성 되 자마자 실행이 시작됩니다. 그래서 당신이 정말로 원하는 것은 약속 공장의 배열입니다 ...

약속에 대해 더 자세히 알고 싶다면 다음 링크를 확인하십시오 : https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html


내 대답은 https://stackoverflow.com/a/31070150/7542429 기반입니다 .

Promise.series = function series(arrayOfPromises) {
    var results = [];
    return arrayOfPromises.reduce(function(seriesPromise, promise) {
      return seriesPromise.then(function() {
        return promise
        .then(function(result) {
          results.push(result);
        });
      });
    }, Promise.resolve())
    .then(function() {
      return results;
    });
  };

이 솔루션은 결과를 Promise.all ()과 같은 배열로 반환합니다.

용법:

Promise.series([array of promises])
.then(function(results) { 
  // do stuff with results here
});

나는 @ joelnet의 대답을 정말로 좋아했지만 나에게 그 코딩 스타일은 소화하기가 약간 어려워서 같은 솔루션을 더 읽기 쉬운 방식으로 표현하는 방법을 알아 내려고 며칠을 보냈습니다. 다른 구문과 주석 만 사용하십시오.

// first take your work
const urls = ['/url1', '/url2', '/url3', '/url4']

// next convert each item to a function that returns a promise
const functions = urls.map((url) => {
  // For every url we return a new function
  return () => {
    return new Promise((resolve) => {
      // random wait in milliseconds
      const randomWait = parseInt((Math.random() * 1000),10)
      console.log('waiting to resolve in ms', randomWait)
      setTimeout(()=>resolve({randomWait, url}),randomWait)
    })
  }
})


const promiseReduce = (acc, next) => {
  // we wait for the accumulator to resolve it's promise
  return acc.then((accResult) => {
    // and then we return a new promise that will become
    // the new value for the accumulator
    return next().then((nextResult) => {
      // that eventually will resolve to a new array containing
      // the value of the two promises
      return accResult.concat(nextResult)
    })
  })
};
// the accumulator will always be a promise that resolves to an array
const accumulator = Promise.resolve([])

// we call reduce with the reduce function and the accumulator initial value
functions.reduce(promiseReduce, accumulator)
  .then((result) => {
    // let's display the final value here
    console.log('=== The final result ===')
    console.log(result)
  })

Bergi가 알다시피, 최선의 명확한 해결책은 BlueBird.each를 사용하는 것입니다.

const BlueBird = require('bluebird');
BlueBird.each(files, fs.readFileAsync);

다음 코드를 사용하여 Promise 개체를 확장합니다. 약속의 거부를 처리하고 결과 배열을 반환합니다.

암호

/*
    Runs tasks in sequence and resolves a promise upon finish

    tasks: an array of functions that return a promise upon call.
    parameters: an array of arrays corresponding to the parameters to be passed on each function call.
    context: Object to use as context to call each function. (The 'this' keyword that may be used inside the function definition)
*/
Promise.sequence = function(tasks, parameters = [], context = null) {
    return new Promise((resolve, reject)=>{

        var nextTask = tasks.splice(0,1)[0].apply(context, parameters[0]); //Dequeue and call the first task
        var output = new Array(tasks.length + 1);
        var errorFlag = false;

        tasks.forEach((task, index) => {
            nextTask = nextTask.then(r => {
                output[index] = r;
                return task.apply(context, parameters[index+1]);
            }, e=>{
                output[index] = e;
                errorFlag = true;
                return task.apply(context, parameters[index+1]);
            });
        });

        // Last task
        nextTask.then(r=>{
            output[output.length - 1] = r;
            if (errorFlag) reject(output); else resolve(output);
        })
        .catch(e=>{
            output[output.length - 1] = e;
            reject(output);
        });
    });
};

function functionThatReturnsAPromise(n) {
    return new Promise((resolve, reject)=>{
        //Emulating real life delays, like a web request
        setTimeout(()=>{
            resolve(n);
        }, 1000);
    });
}

var arrayOfArguments = [['a'],['b'],['c'],['d']];
var arrayOfFunctions = (new Array(4)).fill(functionThatReturnsAPromise);


Promise.sequence(arrayOfFunctions, arrayOfArguments)
.then(console.log)
.catch(console.error);

원하는 경우 다음과 같이 reduce를 사용하여 순차적 약속을 할 수 있습니다.

[2,3,4,5,6,7,8,9].reduce((promises, page) => {
    return promises.then((page) => {
        console.log(page);
        return Promise.resolve(page+1);
    });
  }, Promise.resolve(1));

항상 순차적으로 작동합니다.


사람들이 왜 그렇게 복잡한 솔루션을 제안하는지 이해가 안됩니다. 여기 더 간단한 논리가 있습니다

Async / Await 사용-ES7을 지원하는 경우 최상의 솔루션

function downloadFile(fileUrl) { ... } // This function return a Promise

async function main()
{
  var filesList = [...];
  for (var i = 0; i <= filesList.length; i++)
  {
    await downloadFile(filesList[i]);
  }
}

비동기 / 대기없이

function downloadFile(fileUrl) { ... } // This function return a Promise

function downloadRecursion(filesList, index)
{
  if (index < filesList.length)
  {
    downloadFile(filesList[index]).then(function()
    {
      index++;
      downloadRecursion(filesList, index); // self invocation - recursion!
    });
  }
  else
  {
    return Promise.resolve();
  }
}

function main()
{
  var filesList = [...];
  downloadFile(filesList, 0);
}

질문의 제목 인 "일관된 약속 해결 (즉, 순서대로)?"을 기반으로 OP는 순차적 호출 자체 보다 정산 약속의 순차적 처리에 더 관심이 있음을 이해할 수 있습니다 .

이 답변이 제공됩니다 :

  • 응답을 순차적으로 처리하는 데 순차적 호출이 필요하지 않음을 보여줍니다.
  • 1 년이 지난 후에도 여전히 관심이있는 경우 OP를 포함하여이 페이지 방문자에게 실행 가능한 대체 패턴을 노출합니다.
  • OP의 주장에도 불구하고, 동시에 전화를 걸고 싶지 않다는 주장도 있지만, 이는 제목이 의미하는대로 순차적으로 응답을 처리하려는 요구에 기반한 가정 일 수도 있습니다.

동시 통화를 원치 않으면 순차 통화 등을 포괄하는 Benjamin Gruenbaum의 답변을 참조하십시오.

그러나 동시 호출을 허용하고 순차적으로 응답을 처리하는 패턴에 관심이있는 경우 (성능 향상을 위해) 계속 읽으십시오.

Promise.all(arr.map(fn)).then(fn)(내가 여러 번 한 것처럼) Promise lib의 멋진 설탕 (특히 Bluebird 's) 을 사용해야한다고 생각 하고 싶지만 ( 이 기사에arr.map(fn).reduce(fn) 의지 하여) 패턴은 다음과 같은 이점이 있습니다.

  • jQuery의 사전 호환 버전조차도 모든 약속 lib와 함께 작동합니다 .then().
  • 한 줄 모드로 원하는 것을 건너 뛰거나 오류를 건너 뛸 수있는 유연성을 제공합니다.

여기에 쓰여진 것입니다 Q.

var readFiles = function(files) {
    return files.map(readFile) //Make calls in parallel.
    .reduce(function(sequence, filePromise) {
        return sequence.then(function() {
            return filePromise;
        }).then(function(file) {
            //Do stuff with file ... in the correct sequence!
        }, function(error) {
            console.log(error); //optional
            return sequence;//skip-over-error. To stop-on-error, `return error` (jQuery), or `throw  error` (Promises/A+).
        });
    }, Q()).then(function() {
        // all done.
    });
};

참고 : 단 하나의 조각 만 Q()Q에 고유합니다. jQuery의 경우 readFile ()이 jQuery 약속을 반환하는지 확인해야합니다. A + 라이브러리를 사용하면 외국 약속이 동화됩니다.

열쇠는 여기에 감소의 인 sequence시퀀스 약속, 취급readFile그들의 창조를 약속하지만.

그리고 일단 당신이 그것을 흡수하면, .map()무대가 실제로 필요하지 않다는 것을 깨달았을 때 약간의 생각이 날 것입니다 ! 전체 작업, 병렬 호출 및 올바른 순서로 직렬 처리를 reduce()단독 으로 수행 할 수 있으며 다음 과 같은 유연성이 추가됩니다.

  • 한 줄만 이동하여 병렬 비동기 호출에서 직렬 비동기 호출로 변환-개발 중에 유용 할 수 있습니다.

Q다시 여기 있습니다 .

var readFiles = function(files) {
    return files.reduce(function(sequence, f) {
        var filePromise = readFile(f);//Make calls in parallel. To call sequentially, move this line down one.
        return sequence.then(function() {
            return filePromise;
        }).then(function(file) {
            //Do stuff with file ... in the correct sequence!
        }, function(error) {
            console.log(error); //optional
            return sequence;//Skip over any errors. To stop-on-error, `return error` (jQuery), or `throw  error` (Promises/A+).
        });
    }, Q()).then(function() {
        // all done.
    });
};

이것이 기본 패턴입니다. 데이터 (예 : 파일 또는 일부 변환)를 호출자에게 전달하려면 약간의 변형이 필요합니다.


귀하의 접근 방식은 나쁘지 않지만 두 가지 문제가 있습니다. 오류를 삼키고 명시 적 약속 건설 반 패턴을 사용합니다.

이 두 가지 문제를 모두 해결하고 동일한 전략을 그대로 유지하면서 코드를 더 깨끗하게 만들 수 있습니다.

var Q = require("q");

var readFile = function(file) {
  ... // Returns a promise.
};

var readFiles = function(files) {
  var readSequential = function(index) {
    if (index < files.length) {
      return readFile(files[index]).then(function() {
        return readSequential(index + 1);
      });
    }
  };

  // using Promise.resolve() here in case files.length is 0
  return Promise.resolve(readSequential(0)); // Start!
};

누군가가 CRUD 작업을 수행 할 때 약속 된 순차 해결 방법을 보장하는 확실한 방법이 필요한 경우 다음 코드를 기본으로 사용할 수도 있습니다.

Promise를 설명하고 각 함수를 호출하기 전에 'return'을 추가하고이 예제를 기본으로 사용하는 한 다음 .then () 함수 호출은 이전 함수를 완료 한 후에 지속적으로 시작됩니다.

getRidOfOlderShoutsPromise = () => {
    return readShoutsPromise('BEFORE')
    .then(() => {
        return deleteOlderShoutsPromise();
    })
    .then(() => {
        return readShoutsPromise('AFTER')
    })
    .catch(err => console.log(err.message));
}

deleteOlderShoutsPromise = () => {
    return new Promise ( (resolve, reject) => {
        console.log("in deleteOlderShouts");
        let d = new Date();
        let TwoMinuteAgo = d - 1000 * 90 ;
        All_Shouts.deleteMany({ dateTime: {$lt: TwoMinuteAgo}}, function(err) {
            if (err) reject();
            console.log("DELETED OLDs at "+d);
            resolve();        
        });
    });
}

readShoutsPromise = (tex) => {
    return new Promise( (resolve, reject) => {
        console.log("in readShoutsPromise -"+tex);
        All_Shouts
        .find({})
        .sort([['dateTime', 'ascending']])
        .exec(function (err, data){
            if (err) reject();
            let d = new Date();
            console.log("shouts "+tex+" delete PROMISE = "+data.length +"; date ="+d);
            resolve(data);
        });    
    });
}

일련의 약속에 배열 푸시 및 팝 방법을 사용할 수 있습니다. 추가 데이터가 필요할 때 새로운 약속을 추진할 수도 있습니다. 이것은 코드입니다. React Infinite 로더에서 일련의 페이지를로드하는 데 사용할 것입니다.

var promises = [Promise.resolve()];

function methodThatReturnsAPromise(page) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log(`Resolve-${page}! ${new Date()} `);
			resolve();
		}, 1000);
	});
}

function pushPromise(page) {
	promises.push(promises.pop().then(function () {
		return methodThatReturnsAPromise(page)
	}));
}

pushPromise(1);
pushPromise(2);
pushPromise(3);


이는 spex.sequence 구현을 기반으로 동적 / 무한 시퀀스를 지원하여보다 일반적인 방식으로 약속 시퀀스를 처리하는 방법을 확장하는 것입니다.

var $q = require("q");
var spex = require('spex')($q);

var files = []; // any dynamic source of files;

var readFile = function (file) {
    // returns a promise;
};

function source(index) {
    if (index < files.length) {
        return readFile(files[index]);
    }
}

function dest(index, data) {
    // data = resolved data from readFile;
}

spex.sequence(source, dest)
    .then(function (data) {
        // finished the sequence;
    })
    .catch(function (error) {
        // error;
    });

이 솔루션은 모든 크기의 시퀀스에서 작동 할뿐만 아니라 데이터 조절 및로드 밸런싱쉽게 추가 할 수 있습니다 .

참고 URL : https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-ie-in-sequence

반응형