我想在循环中延迟一段时间后执行一些代码。一旦完成所有迭代,我想做其他一些任务。这些取决于从task1获得的结果。为此,我使用生成器,async / await和promise编写了以下代码片段:
function* iter() {
for (var i = 0; i < 10; i++) yield i
}
async function start() {
var myIter = iter();
var p = await cb1(myIter);
console.log('after await');
p.then((value) => {
console.log('-----------here-------------');
});
}
start();
function cb1(myIter) {
console.log("Started : " + new Date());
var obj;
return new Promise((resolve, reject) => {
setTimeout(function(){
if(myIter.next().done === true) {
console.log("End : " + new Date());
resolve('done');
}else {
console.log("---in else---");
cb1(myIter);
}
}, 3000);
});
}
问题在于,永远不会打印p.then()中的控制台。这意味着承诺永远不会得到解决,程序会终止。迭代按预期执行,但是承诺永远无法解决。这有什么问题吗?我正在使用递归来触发iterator.next(),并且只想在最后一次迭代(即done = true时)上解决承诺。
很久以来,我一直在这个问题上挠头。感谢帮助。以下是该程序的输出。
答案 0 :(得分:2)
几个问题:生产线
var p = await cb1(myIter);
为p
分配了调用cb1
的结果的值。除非构造的p
也解析为Promise
,否则Promise
也不是Promise
,这是不寻常的。因为await
实际上会暂停脚本的执行,直到承诺解决为止,所以您不需要.then
-您只需要在console.log
函数中添加下面的start
。一旦将诺言正确地链接在一起,p
就会解析为'done'
的 string ,这当然不是Promise
。
但是还有另一个问题:cb1
返回的诺言永远都无法解决,除非在最后,您要呼叫resolve
。在else
中,您永远不会打电话给resolve
,因此这些承诺永远永远都没有解决。要解决此问题,请更改
} else {
console.log("---in else---");
cb1(myIter);
}
到
} else {
console.log("---in else---");
cb1(myIter).then(resolve);
}
,以便下一个迭代的Promise
解析后,当前迭代的Promise
解析。
function* iter() {
for (var i = 0; i < 3; i++) yield i
}
async function start() {
var myIter = iter();
var p = await cb1(myIter);
console.log('after await');
console.log('-----------here-------------');
}
start();
function cb1(myIter) {
console.log("Started : " + new Date());
var obj;
return new Promise((resolve, reject) => {
setTimeout(function() {
if (myIter.next().done === true) {
console.log("End : " + new Date());
resolve('done');
} else {
console.log("---in else---");
cb1(myIter).then(resolve);
}
}, 1000);
});
}
答案 1 :(得分:1)
还需要1个功能,然后它才能起作用:
function* iter() {
for (var i = 0; i < 10; i++) yield i
}
async function start() {
var myIter = iter();
var p = await cb1(myIter);
console.log('after await');
console.log("here is p:" + p.done + "," + p.value);
}
start();
function repeat(myIter,resolver,previous){
var temp;
if((temp = myIter.next()).done === true) {
console.log("End : " + new Date());
resolver(previous);
}else {
console.log("---in else---");
setTimeout(function(){repeat(myIter,resolver,temp)},3000);
}
}
function cb1(myIter) {
console.log("Started : " + new Date());
var obj;
return new Promise((resolve, reject) => {
repeat(myIter,resolve);
});
}
还修复了p,等待将其取出,您需要获取先前的值
答案 2 :(得分:1)
有两个问题:
await
的结果永远不会是一个承诺; await
的目的是等待承诺解决,并为您提供分辨率值。因此,您代码中的p
并不是一个承诺,也不会有then
方法。但是由于#2,您不会因此而出错。cb1
的resolve
函数创建一个新的Promise。您的最后一个setTimeout
回调正在解决最后一个诺言,但是没有一个解决第一个诺言,因此您永远不会越过var p = await cb1(myIter);
行。您可能需要一个用于计时器回调的内部函数,然后通过cb1
调用返回的promise进行解析。
遵循以下原则:
function* iter() {
for (var i = 0; i < 10; i++) {
yield i;
}
}
async function start() {
var myIter = iter();
var p = await cb1(myIter);
console.log("p = ", p);
}
start();
function cb1(myIter) {
console.log("Started : " + new Date());
return new Promise((resolve, reject) => {
iteration();
function iteration() {
setTimeout(function() {
if (myIter.next().done) { // `=== done` is pointless here
console.log("End : " + new Date());
resolve('done');
} else {
console.log("---in else---");
iteration();
}
}, 3000);
}
});
}