2017-06-14 196 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

相关问题