从承诺中返回一个值:回调还是承诺?
Returning a value from a promise: callback or promise?
(* 我修改了我最初的问题... *)
我有一个异步函数 calculate
,它重新计算 Excel 工作簿并打印它需要多长时间。
然后,我想把函数做成return计算时间,这样我就可以记录下来。它考虑使一个异步函数 return 成为一个值。我阅读了几个线程,并编写了以下两种有效的方法:
function calculate1 (mode, fn) {
return Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
return ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
document.getElementById("b").value += 'inside: ' + t + '\n';
fn(t);
})
})
}
function calculate2 (mode) {
return new Promise(function (resolve, reject) {
return Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
return ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
document.getElementById("b").value += 'inside: ' + t + '\n';
resolve(t); })
})
})
}
这是测试:
function test () {
var a = [];
var pm = new OfficeExtension.Promise(function(resolve, reject) { resolve (null); });
pm
.then(function() { return calculate1('FullRebuild', function (t) {
a.push(t); }); })
.then(function() { return calculate1('FullRebuild', function (t) {
a.push(t); }); })
.then(function() { return calculate2('FullRebuild').then(function (result) {
a.push(result); }); })
.then(function() { return calculate2('FullRebuild').then(function (result) {
a.push(result); }); })
.then(function() {
document.getElementById("b").value += a.toString() + '\n'; });
}
我猜 calculate1
使用 callback
,而 calculate2
使用 promise
。谁能告诉我哪种方式更好?
此外,fn(t)
(相应的,resolve(t)
)在正确的位置,还是我应该将其包装在另一个 then
中?
PS:Excel.run
和ctx.sync()
是JavaScript API for Office的函数;他们都return一个承诺。
calculate1()
是 promises 和回调的糟糕组合,而 calculate2()
展示了 Explicit Promise Construction Antipattern.
以下是正确使用 promises 而不会造成任何额外浪费的方法:
function calculate1 (mode) {
return Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
return ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
document.getElementById("b").value += 'inside: ' + t + '\n';
return t;
});
});
}
然后就可以这样消费了。请注意,它使用的函数比您尝试的要少得多:
return calculate1('FullRebuild')
.then(function(res) {
a.push(res);
return calculate1('FullRebuild');
})
.then(function(res) {
a.push(res);
return calculate1('FullRebuild');
})
.then(function(res) {
a.push(res);
return calculate1('FullRebuild');
})
.then(function(res) {
a.push(res);
document.getElementById("b").value += a.toString() + '\n';
});
如果您想要一个异步函数 return 一个值 - 而不是将回调传递给它 - return 值需要包装在一个承诺中并像第二个示例中那样解析。
promise 的便利在于它避免了回调嵌套 -> 当一个回调需要另一个回调时...
错误传播到最近的 Promise.catch() 块
的方式
function calculate2 (mode) {
return new Promise(function (resolve, reject) {
Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
resolve(t);
})
})
})
}
calculate2('FullRebuild')
.then(function (t) {
document.getElementById("b").value += 'inside: ' + t + '\n';
// the return value of a promise resolver is wrapped in a promise too
// and the value of t will be available as parameter of the following .then(funtion(t)) block
return t;
})
.catch(function(err) {
// Addresses potential async errors raised since calling calculate2()
});
(* 我修改了我最初的问题... *)
我有一个异步函数 calculate
,它重新计算 Excel 工作簿并打印它需要多长时间。
然后,我想把函数做成return计算时间,这样我就可以记录下来。它考虑使一个异步函数 return 成为一个值。我阅读了几个线程,并编写了以下两种有效的方法:
function calculate1 (mode, fn) {
return Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
return ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
document.getElementById("b").value += 'inside: ' + t + '\n';
fn(t);
})
})
}
function calculate2 (mode) {
return new Promise(function (resolve, reject) {
return Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
return ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
document.getElementById("b").value += 'inside: ' + t + '\n';
resolve(t); })
})
})
}
这是测试:
function test () {
var a = [];
var pm = new OfficeExtension.Promise(function(resolve, reject) { resolve (null); });
pm
.then(function() { return calculate1('FullRebuild', function (t) {
a.push(t); }); })
.then(function() { return calculate1('FullRebuild', function (t) {
a.push(t); }); })
.then(function() { return calculate2('FullRebuild').then(function (result) {
a.push(result); }); })
.then(function() { return calculate2('FullRebuild').then(function (result) {
a.push(result); }); })
.then(function() {
document.getElementById("b").value += a.toString() + '\n'; });
}
我猜 calculate1
使用 callback
,而 calculate2
使用 promise
。谁能告诉我哪种方式更好?
此外,fn(t)
(相应的,resolve(t)
)在正确的位置,还是我应该将其包装在另一个 then
中?
PS:Excel.run
和ctx.sync()
是JavaScript API for Office的函数;他们都return一个承诺。
calculate1()
是 promises 和回调的糟糕组合,而 calculate2()
展示了 Explicit Promise Construction Antipattern.
以下是正确使用 promises 而不会造成任何额外浪费的方法:
function calculate1 (mode) {
return Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
return ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
document.getElementById("b").value += 'inside: ' + t + '\n';
return t;
});
});
}
然后就可以这样消费了。请注意,它使用的函数比您尝试的要少得多:
return calculate1('FullRebuild')
.then(function(res) {
a.push(res);
return calculate1('FullRebuild');
})
.then(function(res) {
a.push(res);
return calculate1('FullRebuild');
})
.then(function(res) {
a.push(res);
return calculate1('FullRebuild');
})
.then(function(res) {
a.push(res);
document.getElementById("b").value += a.toString() + '\n';
});
如果您想要一个异步函数 return 一个值 - 而不是将回调传递给它 - return 值需要包装在一个承诺中并像第二个示例中那样解析。
promise 的便利在于它避免了回调嵌套 -> 当一个回调需要另一个回调时... 错误传播到最近的 Promise.catch() 块
的方式function calculate2 (mode) {
return new Promise(function (resolve, reject) {
Excel.run(function (ctx) {
ctx.workbook.application.calculate(mode);
var before = performance.now();
ctx.sync().then(function() {
var after = performance.now();
var t = after - before;
resolve(t);
})
})
})
}
calculate2('FullRebuild')
.then(function (t) {
document.getElementById("b").value += 'inside: ' + t + '\n';
// the return value of a promise resolver is wrapped in a promise too
// and the value of t will be available as parameter of the following .then(funtion(t)) block
return t;
})
.catch(function(err) {
// Addresses potential async errors raised since calling calculate2()
});