2017-03-29 16 views
5
var myArray = [1, 2, 3, 4, 5, 6] 

function myPrommise(num){ 
    return new Promise(res => { 
    window.setTimeout(()=>{ 
     res( console.log("done: " + num) ) 
    },2000) 
    }) 
} 


myPrommise(myArray[0]) 
    .then(x => myPrommise(myArray[1])) 
    .then(x => myPrommise(myArray[2])) 
    .then(x => myPrommise(myArray[3])) 
    .then(x => myPrommise(myArray[4])) 
    .then(x => myPrommise(myArray[5])) 

Ngay bây giờ, nếu tôi thực hiện tuyên bố ở trên, nó sẽ chạy tuần tự. Trong trường hợp sử dụng thực tế của tôi, mảng được điền động và tôi cần phải thực hiện chức năng myPromise() cho mỗi thành viên trong myArray.Làm thế nào để thực thi các lời hứa tuần tự, chuyển các tham số từ một mảng?

Làm cách nào để tạo "vòng lặp tạm dừng" lặp lại cho từng mục trong mảng, thực hiện myPromise và chờ lời hứa được giải quyết trước khi tiếp tục lặp lại tiếp theo?

+1

Promise.All là những gì bạn muốn –

+1

@JohnPeters On riêng của mình, đó là chưa đủ, bởi vì nó sẽ không giải quyết tuần tự. – 4castle

Trả lời

15

Bạn có thể làm cho việc áp dụng lặp đi lặp lại của .then vào một lần:

myArray.reduce(
    (p, x) => 
    p.then(_ => myPromise(x)), 
    Promise.resolve() 
) 

Bluebird, một thư viện lời hứa tuyệt vời bạn nên sử dụng nếu bạn không, cũng has mapSeries built in:

Promise.mapSeries(myArray, myPromise) 

Runnable snippet:

const myArray = [1, 2, 3, 4, 5, 6] 
 

 
const sleep = ms => 
 
    new Promise(res => { 
 
    setTimeout(res, ms) 
 
    }) 
 

 
const myPromise = num => 
 
    sleep(500).then(() => { 
 
    console.log('done: ' + num) 
 
    }) 
 

 
myArray.reduce(
 
    (p, x) => 
 
    p.then(_ => myPromise(x)), 
 
    Promise.resolve() 
 
)

+1

Nếu bạn cần tất cả các kết quả trả lại như với 'Promise.all' -' myArray.reduce ((p, x) => p.then (kết quả => fn (x) .then (r => results.concat (r))), Promise.resolve ([])). (Kết quả => {}); ' –

0

Tôi sẽ sử dụng babel và làm theo cách này:

let args = [1, 2, 3]; 
 
    
 
    const myPromise = async x => console.log('arg:',x); 
 
    
 
    const test = async() => { 
 
     for (let task of args.map(myPromise)) 
 
     await task; 
 
    } 
 
    
 
    test().then(console.log('Done'));
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>

+1

Tôi tin rằng ví dụ thứ hai của bạn không được bảo đảm để chạy tuần tự. –

1

Bạn có thể sử dụng Array.reduce.

//type: [number] 
var myArray = [1, 2, 3, 4, 5, 6] //doesn't really matter 

//type: number -> Promise<number> 
function myPromise(num){ 
    return new Promise((resolve) => { 
    window.setTimeout(()=>{ 
     resolve(console.log("done: " + num) ) 
    },2000) 
    }) 
} 

//Array.reduce has type: [a] ~> ((b, a) -> b), b) -> b 
//So it can have type: 
//[number] ~> ((Promise<number> -> number -> Promise<number>), Promise<number>) -> Promise<number> 
//Therefore we need to give reduce a function that takes a Promise 
//resolving to a number and a number which makes a new promise. 
//This is the function we want: 

function sequencePromises(promise, number) { 
    return new Promise((resolve) => { 
    resolve(promise.then(_ => myPromise(number))); 
    } 
} 

myArray.reduce(sequencePromises, Promise.resolve()); 

Tất nhiên, cách tiếp cận đơn giản này sẽ không hoạt động nếu bạn có một lời hứa mà có thể lỗi, hoặc nếu bạn cần kết quả trước đó, vì vậy bạn có thể muốn làm chung sequencePromises hơn:

function genericSequencePromises(promiseFunction) { 
    return (promise, parameter) => { 
    return new Promise((resolve, reject) => 
         return promiseFunction(resolve, 
               reject, 
               promise, 
               parameter)); 
    } 
} 

Sau đó, bạn có thể làm bất cứ điều gì bạn muốn miễn là bạn trả lại một Promise.

Cuối cùng, bạn có thể được hưởng lợi từ helper ít này:

function promiseSeries(array, reducer) { 
    return array.reduce(reducer, Promise.resolve()); 
} 

Đưa nó tất cả cùng nhau:

let sequencePromises = genericSequencePromises((resolve, reject, promise, num) => { 
    resolve(promise.then(_ => console.log(`done: ${num}`))); 
} 

promiseSeries(myArray, sequencePromises); 

Bằng cách này, bạn có thể không chỉ xử lý các trường hợp trong câu hỏi của bạn, nhưng nhiều hơn nữa trường hợp phức tạp.

0

Bạn có thể lặp qua mảng các phần tử và vượt qua params như thế này:

const arr = [1, 2, 3, 4, 5, 6]; 
 
const MyPromiseFunction = num => new Promise((resolve, reject) => { 
 
    // Your logic... 
 
    setTimeout(() => num <= 4 
 
    ? resolve('Success!') 
 
    : reject('Rejected!'), 1000 * num); 
 
}); 
 
const logMessage = (num, msg) => console.log(`For number ${num} promise result: ${msg}`); 
 

 
arr.forEach(
 
    num => MyPromiseFunction(num) 
 
    .then(message => logMessage(num, message)) 
 
    .catch(reason => logMessage(num, reason)) 
 
);

Các vấn đề liên quan