var stepsToDo = [step1, step2, step3,...]
每一步都进行ajax调用:
function step1() { return $.ajax({ ... }); }
function step2() { return $.ajax({ ... }); }
step 1
(step 2
和其他人的类似ajax调用示例):
return $.ajax({
url: "test.php",
type: "POST",
dataType: "json",
data: {"step-1": ""},
beforeSend: function () {
writeResult("Processing-> test 1");
},
success: function (result) {
if (result) {
if (result instanceof Array) {
writeResult("Found: " + result.length + " items");
arr = result;
} else {
writeResult(result);
arr = [];
}
}
}
});
function writeResult(str) { console.log(str); }
我想按顺序执行(在stepsToDo中定义)。
我试过了:
stepsToDo.reduce(
(promise, method) => {
return promise.then(method);
},
Promise.resolve()
);
没有任何反应,控制台中没有打印。
为什么?
答案 0 :(得分:1)
放弃new Promise
。您的步骤是返回承诺的函数,而不是promise executors - 它们永远不会调用传递给它们的resolve
回调。
答案 1 :(得分:0)
对于您最初创建的reducer功能......
stepsToDo.reduce((promise, method) => {
return promise.then(_ => new Promise(method));
}, Promise.resolve());
...你的步骤函数应该resolve
或reject
在reducer中创建的promise - 因此应该实现promise执行者签名,I.E:
type executor = (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void;
例如:
function step1(resolve, reject) {
$
.ajax({ /* ... */ })
.done(resolve)
.fail(reject);
}
修改强>
正如@Bergi在评论中所述,这是is an anti-pattern。相反,您可以将Promise构造移动到步骤函数中。一个基本的例子(jQuery ajax API仍然必须转换为promises)
function step1() {
return new Promise((resolve, reject) => {
$.ajax({ /* ... */ }).done(resolve).fail(reject);
});
}
如果您的所有步骤都返回了您的承诺,您的减速器可以变得更简单:
stepsToDo.reduce((promise, method) => promise.then(method), Promise.resolve());
在这种情况下,您甚至可以返回$.ajax
的结果,因为jQuery promises会实现 then 方法:
function step1() {
return $.ajax({ /* ... */ });
}
如果错误处理需要本机承诺,即Promise.catch
,您可以使用Promise.resolve
显式地将jQuery承诺强制转换为本机承诺:
function step1() {
return Promise.resolve($.ajax({ /* ... */ }));
}
答案 2 :(得分:0)
我不确定其他答案有什么问题,但$ .get(或ajax或post)会返回一个承诺。
所以你的步骤方法可能如下所示:
var stepOne = () => {
return $.ajax({//just return the promise like
url: "test.php",
type: "POST",
dataType: "json",
data: {"step-1": ""}
});
}
然后,您可以将其减少为一个通过三个步骤的结果解决的承诺:
[stepOne,stepTwo,stepThree].reduce(
(p,fn)=>
p.then(
results=>fn().then(result=>results.concat([result]))
),
$.Deferred().resolve([])
)
.then(
results=>console.log("got results:",results),
err=>console.warn("Something went wrong:",err)
);
你看我没有通过Promise.resolve
作为第二个参数来减少$.Deferred().resolve([])
,这是jQuery承诺的价值。您现在可以支持不具备本机承诺的浏览器,而无需进行填充。
虽然如果您需要支持那些我建议不使用箭头功能语法并使用function(something){return something}
代替something=>something
答案 3 :(得分:0)
原始问题或实施中缺少大部分内容。如果所有步骤函数都返回$.ajax
承诺,则Array.reduce
模式应该有效。
以下是使用step()
函数模拟异步代码执行并使用完全相同的Array.reduce
模式的概念的工作证明:
// Step generator
function step(number) {
return function() {
return $.Deferred(function(def) {
setTimeout(function() {
console.log('Running Step ', number);
def.resolve();
}, Math.floor(Math.random() * Math.floor(250)));
}).promise();
}
}
// List of steps
var stepsToDo = [step(1), step(2), step(3), step(4), step(5)];
// Consume steps one at a time
stepsToDo.reduce(
(promise, method) => {
return promise.then(method);
},
Promise.resolve()
).then(() => console.log('All Done!'));
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;