如何正确使用 defer() ?
How to use defer() the right way?
如何正确使用defer?我这里有两个函数,其中一个延迟使用正确?它在哪一个中使用不正确?以及为什么要回答。为什么不呢?
第一个例子:
getFoo1: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
console.log(err);
dfd.reject(err);
} else {
var qcs = [];
for(var i=0; i < response.total_rows; i++) {
if(response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
oneFunction(qc)
.then(anotherFunction(qc))
.then(qcs.push(qc));
}
}
dfd.resolve(qcs);
}
});
return dfd.promise;
},
第二个例子:
getFoo2: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
dfd.reject(err);
} else {
dfd.resolve(response);
}
});
return dfd.promise
.then(function(response) {
var foo = [];
for(var i=0; i < response.total_rows; i++) {
if(response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
return oneFunction(qc)
.then(anotherFunction(qc))
.then(foo.push(qc));
}
}
}, function(err){
console.log(err);
});
},
oneFunction
不执行任何异步操作。
anotherFunction
异步执行某些操作(从外部数据库检索数据)。
编辑:感谢@Bergi,正确的函数应该是这样的:
getFoo3: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
dfd.reject(err);
} else {
dfd.resolve(response);
}
});
return dfd.promise
.then(function(response) {
var foos = [];
for (var i=0; i < response.total_rows; i++) {
if (response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
var foo = oneFunction(qc);
foos.push(foo);
}
}
var promises = foos.map(anotherFunction); // make a promise for each foo
return $q.all(promises);
}, function(err){
console.log(err);
});
},
您在第二个示例中正确使用了 $q.defer
[1] - 为 db.allDocs
异步调用(以及没有其他的)。虽然 pochdb 似乎已经 return 承诺,正如@Benjamin 在评论中提到的那样,所以这是不必要的(但没有错)。
第一个例子一团糟,将 promise 的构造与错误日志记录和那个不祥的循环缠绕在一起。
1:除了dfd.promise()
,它不是函数而是属性。争取 dfd.promise.then(…)
.
但是,该循环是一个非常不同的主题,并且在两个片段中似乎都是错误的。几点:
- 在第二个片段中,您的
return
来自循环主体中的回调函数,就在满足谓词的第一次迭代中。
- 如果
oneFunction(qc)
不是异步的,它不需要(阅读:不应该)return 一个承诺 - 或者如果不需要,那么 .then(…)
调用是错了。
anotherFunction(qc)
似乎 return 一个承诺(如您所说,它是异步的)。但是您不能将该承诺传递给 .then()
,那里需要一个回调函数!
foo.push(qc)
也一样 - 它不是您要传递给 .then()
的回调函数。
- 毕竟,您在该循环中执行异步操作。在这里,
Promise.all
现在!
如果非要我打赌,我会说你需要
.then(function(response) {
var foos = [];
for (var i=0; i < response.total_rows; i++) {
if (response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
var foo = oneFunction(qc);
foos.push(foo);
}
}
var promises = foos.map(anotherFunction); // make a promise for each foo
return $q.all(promises);
})
如何正确使用defer?我这里有两个函数,其中一个延迟使用正确?它在哪一个中使用不正确?以及为什么要回答。为什么不呢?
第一个例子:
getFoo1: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
console.log(err);
dfd.reject(err);
} else {
var qcs = [];
for(var i=0; i < response.total_rows; i++) {
if(response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
oneFunction(qc)
.then(anotherFunction(qc))
.then(qcs.push(qc));
}
}
dfd.resolve(qcs);
}
});
return dfd.promise;
},
第二个例子:
getFoo2: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
dfd.reject(err);
} else {
dfd.resolve(response);
}
});
return dfd.promise
.then(function(response) {
var foo = [];
for(var i=0; i < response.total_rows; i++) {
if(response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
return oneFunction(qc)
.then(anotherFunction(qc))
.then(foo.push(qc));
}
}
}, function(err){
console.log(err);
});
},
oneFunction
不执行任何异步操作。
anotherFunction
异步执行某些操作(从外部数据库检索数据)。
编辑:感谢@Bergi,正确的函数应该是这样的:
getFoo3: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
dfd.reject(err);
} else {
dfd.resolve(response);
}
});
return dfd.promise
.then(function(response) {
var foos = [];
for (var i=0; i < response.total_rows; i++) {
if (response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
var foo = oneFunction(qc);
foos.push(foo);
}
}
var promises = foos.map(anotherFunction); // make a promise for each foo
return $q.all(promises);
}, function(err){
console.log(err);
});
},
您在第二个示例中正确使用了 $q.defer
[1] - 为 db.allDocs
异步调用(以及没有其他的)。虽然 pochdb 似乎已经 return 承诺,正如@Benjamin 在评论中提到的那样,所以这是不必要的(但没有错)。
第一个例子一团糟,将 promise 的构造与错误日志记录和那个不祥的循环缠绕在一起。
1:除了dfd.promise()
,它不是函数而是属性。争取 dfd.promise.then(…)
.
但是,该循环是一个非常不同的主题,并且在两个片段中似乎都是错误的。几点:
- 在第二个片段中,您的
return
来自循环主体中的回调函数,就在满足谓词的第一次迭代中。 - 如果
oneFunction(qc)
不是异步的,它不需要(阅读:不应该)return 一个承诺 - 或者如果不需要,那么.then(…)
调用是错了。 anotherFunction(qc)
似乎 return 一个承诺(如您所说,它是异步的)。但是您不能将该承诺传递给.then()
,那里需要一个回调函数!foo.push(qc)
也一样 - 它不是您要传递给.then()
的回调函数。- 毕竟,您在该循环中执行异步操作。在这里,
Promise.all
现在!
如果非要我打赌,我会说你需要
.then(function(response) {
var foos = [];
for (var i=0; i < response.total_rows; i++) {
if (response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
var foo = oneFunction(qc);
foos.push(foo);
}
}
var promises = foos.map(anotherFunction); // make a promise for each foo
return $q.all(promises);
})