javascript - 如果未传递可选回调,如何使函数返回承诺?
问题描述
我可以想出
function squareAsync(val, callback) {
if (callback) {
setTimeout(() => {
if (Math.random() < 0.5) {
callback(undefined, val * val);
}
else {
callback(new Error('Failed!'));
}
}, 2000);
}
else {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
resolve(val * val);
}
else {
reject(new Error('Failed!'));
}
}, 2000);
});
}
}
我为此找到了另一种方法
function squareAsync1(val, callback) {
let p = new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
resolve(val * val);
}
else {
reject(new Error('Failed!'));
}
}, 2000);
});
if (callback) {
p.then(d => {
callback(undefined, d);
}, e => {
callback(e);
});
}
return p;
}
其中哪一个更好,或者有更标准和更优雅的方式来做到这一点?我们可以这样做async/await
吗?
解决方案
你可以这样做:
function squareAsync(val, callback) {
const timeout = function(res, rej){
setTimeout(function(){
if (Math.random() < 0.5)
res(val*val);
else
rej(new Error('Failed!'));
}, 2000);
}
return typeof callback === 'function'
? timeout(callback.bind(null, undefined), callback)
: new Promise(timeout);
}
// CALLBACK EXAMPLE
squareAsync(5, (err, val) => {
if (err)
console.log(`Callback: ${err}`);
else
console.log(`Callback: ${val}`);
})
// PROMISE EXAMPLE
squareAsync(5)
.then(val => console.log(`Promise: ${val}`))
.catch(err => console.log(`Promise: ${err}`))
解释
- 将您的
setTimeout
调用包装到一个包装函数timeout
中,这样您就不必重复几乎相同的代码。 - 让
timeout
函数接受两个参数:res
andrej
(resolve and reject) timeout
如果回调是通过函数传递的,则返回,否则返回new Promise(timeout)
。
现在关于发生了什么:
return typeof callback === 'function'
? timeout(callback.bind(null, undefined), callback)
: new Promise(timeout);
它转化为:
if (typeof callback === 'function'){
// Bind `null` as `this` value to `callback
// and `undefined` as its first argument (because no error).
// Need to to this because in `timeout` function,
// we call `res` with only 1 argument (computed value) if success.
const resolve = callback.bind(null, undefined);
// Don't need to bind anything
// because the first argument should be error.
const reject = callback;
// Call the function as if we are in a Promise
return timeout(resolve, reject);
}
// Use `timeout` function as normal promise callback.
return new Promise(timeout);
希望你能理解。如果感到困惑,请随时发表评论。
推荐阅读
- firebase - Firebase 电话身份验证上的 APP 验证错误
- python - 如何在 django 中设计一个通用的 views.py 函数
- javascript - 在 JavaScript 中缩小 URL
- android - 如何在android中为动态表格布局行应用搜索过滤器
- sql - 无法在 phpMyAdmin 上添加帐户/没有管理用户的权限
- html - 带有 {bslib} 包的 R Shiny 1.6:移动设备上的导航栏样式 - Bootstrap 4 与 Bootstrap 3
- javascript - 如何在 Angular 应用程序的 html 块中查看脚本函数值?
- api - 在颤振中用双引号传递参数值 -
- spring-boot - Jackson - 从嵌套元素开始
- angular - p-columnFilter 不是已知元素