如何在ES6中将回调代码转换为promise
How to convert a callback code to promise in ES6
我正在学习ES6标准,所以我从一个非常基本的示例代码开始。
JavaScript中存在回调shell,所以这次我确实想避免使用回调。但我遇到了一个问题,我真的不知道如何将回调风格的代码转换为promise。
例如,如果我有这样的代码看起来像下面的
module.exports = (x, y, callback) => {
try {
if (x < 0 || y < 0) {
throw new Error('Rectangle dimensions are wrong.');
} else {
callback(null, {
perimeter() {
return (2 * (x + y));
},
area() {
return (x * y);
},
});
}
} catch (error) {
callback(error, null);
}
};
我应该如何在ES6中将其转换为Promise
?这是一种将回调转换为承诺的推荐行为吗?
我读过这个例子,但实际上我对结果感到困惑。我想在我开始重写我的回电到承诺之前,我需要先理解这一点。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('Resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// Resolved
我的理解是Promise
在创建后立即运行。但我不知道为什么then
方法中的代码会最后运行。
现有的答案成为延迟反模式的牺牲品。我会避免这种方法,因为它不必要地冗长,并且没有利用完整的Promise API。另一个答案使用了承诺。只有当您无法更改使用回调样式编写的代码(例如使用第三方脚本(时,才真正需要使用promisification。
你问了两个问题,第二个问题是为什么Promises的行为会像你在给定的例子中看到的那样。为了找到这个问题的答案,我建议你使用关于SO的许多现有问题。例如,Promises不就是回调吗?
关于你的第一个问题,如何重构你的代码以使用Promises,这里是我的建议:
module.exports = (x, y) => {
if (x < 0 || y < 0) {
return Promise.reject(new Error('Rectangle dimensions are wrong.'));
} else {
return Promise.resolve({
perimeter() {
return (2 * (x + y));
},
area() {
return (x * y);
},
});
}
};
// e.g. success
createRectangle(10, 10)
.then(rect => {
console.log(rect.area()) //=> 100
})
// e.g. failure
createRectangle(-1, -1)
.catch(err => {
console.log(err) //=> "Error: Rectangle dimensions are wrong."
})
由于函数本身并不依赖于异步操作的完成,我们可以使用助手方法Promise#resolve
和Promise#reject
从函数中返回一个Promise,表示创建"矩形"对象的成功或失败。这会产生一个新的Promise,其状态被解析或拒绝,分别带有一个值或一个错误。
module.exports = (x, y, callback) => {
new Promise(function(resolve, reject) {
if (x < 0 || y < 0) reject(new Error('Rectangle dimensions are wrong.'))
else resolve({
perimeter() {
return (2 * (x + y));
},
area() {
return (x * y);
}
})
})
.then(callback)
.catch(callback)
}
记住".then"answers".catch"是异步的。
这是一个重要的主题。为了以同步方式进行功能编码,使用promise的目的是将callback
中的逻辑移动到then
阶段。因此,尽管你可以,但你不应该在承诺本身中处理逻辑,而是在then
阶段。这种思维方式有助于我们创建一个通用的promisify实用函数,该函数适用于所有特定类型的回调结构。在您的情况下,回调类型是Node标准错误优先类型。所以根据下面的代码
module.exports = (x, y, callback) => {
try {
if (x < 0 || y < 0) {
throw new Error('Rectangle dimensions are wrong.');
} else {
callback(null, {
perimeter() {
return (2 * (x + y));
},
area() {
return (x * y);
},
});
}
} catch (error) {
callback(error, null);
}
};
一般的promify函数应该如下工作;
var moduleExports = (x, y, callback) => {
try {
if (x < 0 || y < 0) {
throw new Error('Rectangle dimensions are wrong.');
} else {
callback(null, {
perimeter() {
return (2 * (x + y));
},
area() {
return (x * y);
},
});
}
} catch (error) {
callback(error, null);
}
};
function promisfy(fun, ...args){
return new Promise((v,x) => fun(...args, (err,data) => !!err ? x(err) : v(data)));
}
var p = promisfy(moduleExports,4,5);
p.then(val => console.log(val,val.area(),val.perimeter()), err => console.log(err));
// p.then(val => callback(null,val), err => callback(err))
因此,在这种特殊情况下,您将得到具有area
和perimeter
函数的结果对象作为值参数提供给then
阶段onFulfillment
。因此,您应该调用逻辑以在onFulfillment
函数中使用它们(then
阶段的第一次回调(,并处理onReject
函数中的任何错误(then
阶段的第二次回调(。我在最后一行显示了这一点,作为上面片段中的注释。
PS:我用v
(看起来像check(来指定resolve
,用x
(显然(来指定promise的reject
回调。
承诺确实很好,但一开始可能有点混乱,请检查以下代码:
module.exports = (x, y) => {
var deferred = q.defer();// this will be our promise
try {
if (x < 0 || y < 0) {
//return an error to be catched by catch method
deferred.reject(new Error('Rectangle dimensions are wrong.'));
} else {
//return the event to the next function with this value
deferred.resolve({
perimeter() {
return (2 * (x + y));
},
area() {
return (x * y);
},
});
}
} catch (error) {
deferred.reject(error);
}
return deferred.promise; //Here return the promise
};
//You will use it like this
module(x,y)
.then(callback)
.then(function(data){
})
.catch(function(error){
});
在我的例子中,当你调用你的模块时,你会立即得到promise,但代码还没有执行,在代码执行后,你会在你的"then"方法中得到事件,或者如果你的catch中发生了什么事情。
我真的很喜欢q库来处理promise,让你可以控制如何返回错误,并在发生错误时停止链。基本上,您可以对函数流进行更多的控制。
希望它能帮助你
- 将javascript代码转换为jquery代码时出错
- 将代码转换为可重用对象
- 将mongoose javascript代码转换为typescript.此引用丢失
- 将JQuery代码转换为等效的JavaScript代码
- 如何在AEM 6.1中使用sightly将jsp代码转换为html
- 使用键/代码转换JavaScript数组
- 将html代码转换为十六进制
- 将一些 C# 代码转换为 Javascript
- 想要将jquery代码转换为纯JavaScript或AngularJS
- 使用 ng-repeat将此 html 代码转换为角度
- 将Javascript代码转换为ReactJS
- 将python代码转换为javascript代码
- 如何将文件类型从Coldfusion代码转换为javascript代码
- 将PHP代码转换为Javascript,将数字读取为句子
- 将js代码转换为jQueryMobile时出错
- 将jQuery切换代码转换为JavaScript
- 将伪代码转换为代码
- 有没有一个工具可以将React Elements的javascript代码转换为JSX
- 将一段JavaScript代码转换为PHP
- 如何将一行咖啡脚本代码转换为多行