2017-06-14 119 views
0

這個問題有很多答案,但是它們中的大多數都同步了promise的解析(即執行結束,而不是執行的開始)。按順序運行promise:每個promise都在前一個結束後開始

This solution假設我們已經有一個函數數組:

var funcs = [foo, bar, baz, qux]; 

如何排列等不執行函數創建的?我曾經嘗試這樣做:

var promises = []; 
for (i = 0 ; i < 3, ++i){ 
    promises.push(someFunction(i)) 
} 

function someFunction(i) { 
    return new Promise((resolve, reject) => { 
     console.log(i); 
     resolve(i); 
    }); 
} 

通過for循環的承諾陣列填充的結束,但someFunction已經執行的4倍。使用Promise.allQ序列只是序列解析。

我該如何實現這些功能開始的真正同步?特別是:

foo().then(bar).then(baz).then(qux); 
+0

檢查這個答案:https://stackoverflow.com/a/44371402/7636961 – wostex

+0

我不認爲內置的承諾API有這個功能。你可以試試藍鳥的Promise.reduce:http://bluebirdjs.com/docs/api/promise.reduce.html –

+0

@KarelG:正是我的問題!我怎樣才能將它推入數組而不調用它?我想在for循環中創建這些承諾。 – Ari

回答

0

您只需要傳遞函數的名稱而不傳遞參數。 在你的榜樣,你叫

 someFunction(i) 

- 你傳遞的參數i,所以這是一個函數調用。 您應該只按他們的名字推送功能。每個函數的參數都是前一個promise中解決的值。

function someFunction(i) { 
    return new Promise((resolve, reject) => { 
     console.log(i); 
     resolve(i+1); // increase the value here 
    }); 
} 

這樣的參數將被傳遞到下一個功能提高1倍。但在鏈中的第一個功能,你應該傳遞參數。 喜歡的東西

someFunction(0).then(someFunction).then(someFunction) 

(在這個解決方案,你不需要陣列。)

+0

那麼我怎樣才能在以後的序列中正確調用這些函數呢? – Ari

+0

@Ari你想要執行3次相同的函數嗎? – Cz01

+0

是的,具有不同的參數。 – Ari

1

問題是

promises.push(someFunction(i)) 
當你填充 promises陣列

,該someFunction是被每次在將其值傳遞給.push方法之前調用。所以它可以按照你想要的更早執行。

解決辦法是不叫它。這並不容易實現,所以我想到了一點(但是很醜陋)。我已經介紹了一個對象{p: ..., val: ...},其中包含該承諾函數的promise函數和值。如果你想提供多個值,只需傳遞一個數組。 apply()方法將它轉換爲你的函數參數。函數callPromise以正確的方式處理函數的執行。

可能有人提出了一個更好的解決方案,但這是我能夠很快想到的。

下面是一個按順序調用promise的例子。我已經添加了一個額外的功能(如果你有另一個功能有多個參數)作爲一個PoC。

var promises = []; 
 
for (let i = 0 ; i < 3; ++i){ 
 
    promises.push({p: someFunction, val: i}); 
 
} 
 

 
promises.push({p: anotherFunction, val: [100,33]}); 
 
promises.push({p: someFunction, val: 4}); 
 

 
function someFunction(i) { 
 
    return new Promise((resolve, reject) => { 
 
     console.log('someFunction, i: ' + i); 
 
     resolve(i); 
 
    }); 
 
} 
 

 
function anotherFunction(i1, i2) { 
 
    return new Promise((resolve, reject) => { 
 
     console.log('anotherFunction, i1: ' + i1 + ', i2: ' + i2); 
 
     resolve(i); 
 
    }); 
 
} 
 

 

 
function callPromise(prom) { 
 
    if(Object.prototype.toString.call(prom.val) !== '[object Array]') prom.val = [prom.val]; 
 
    return prom.p.apply(null, prom.val); 
 
} 
 

 
console.log('before loop'); 
 
let result = callPromise(promises[0]); 
 
for (let i = 1 ; i < promises.length; ++i) { 
 
    result = result.then(callPromise(promises[i])); 
 
}

+0

您能解釋一下callPromise到底在做什麼嗎? – Ari

+0

@Ari'prom'是'{p:...,val:...}'對象。它首先檢查val是否是一個數組。如果不是,則將其作爲一個數組。然後它使用'.apply'與val數組運行函數'p'。如果你檢查它的文檔,你會發現數組是作爲參數提供給函數p的。該函數返回一個承諾,然後可以像承諾一樣處理:使用'.then'和'.catch'等... – KarelG

相關問題