如何将现有的回调API转换为承诺?
我想使用承诺,但我有一个格式的回调API:
1. DOM负载或其他一次性事件:
window.onload; // set to callback
...
window.onload = function(){
};
2.普通回调:
function request(onChangeHandler){
...
}
request(function(){
// change happened
...
});
3.节点样式回调(“nodeback”):
function getStuff(dat,callback){
...
}
getStuff("dataParam",function(err,data){
...
})
4.具有节点样式回调的整个库:
API;
API.one(function(err,data){
API.two(function(err,data2){
API.three(function(err,data3){
...
});
});
});
我如何在承诺中使用API,如何“promisify”它?
承诺有国家,他们开始等待,并可以解决:
承诺返回函数不应该抛出,他们应该返回拒绝。 从promise返回函数抛出将迫使你使用} catch {
和.catch
。 使用promisified APIs的人不会期望承诺会抛出。 如果你不确定异步API如何在JS中工作 - 请首先看到这个答案。
1. DOM负载或其他一次性事件:
因此,创建承诺一般意味着指定何时他们解决 - 这意味着当他们转移到履行或拒绝阶段,以表明数据可用(并可以通过.then
访问)。
使用支持Promise
构造函数(如本地ES6)的现代承诺实现承诺:
function load(){
return new Promise(function(resolve,reject){
window.onload = resolve;
});
}
然后,您会使用如此产生的承诺:
load().then(function(){
// Do things after onload
});
使用支持延迟的库(让我们在这里使用$ q作为示例,但我们也将在以后使用jQuery):
function load(){
var d = $q.defer();
window.onload = function(){ d.resolve(); };
return d.promise;
}
或者使用类似API的jQuery,可以连接一次发生的事件:
function done(){
var d = $.Deferred();
$("#myObject").once("click",function(){
d.resolve();
});
return d.promise();
}
2.普通回调:
这些API很常见,因为...回调在JS中很常见。 让我们看看有onSuccess
和onFail
的常见情况:
function getUserData(userId, onLoad, onFail){ ...
使用支持Promise
构造函数(如本地ES6)的现代承诺实现承诺:
function getUserDataAsync(userId){
return new Promise(function(resolve,reject){
getUserData(userId,resolve,reject);
});
}
使用支持延迟的库(让我们在这里使用jQuery作为这个例子,但是我们也使用了上面的$ q):
function getUserDataAsync(userId){
var d = $.Deferred();
getUserData(userId,function(res){ d.resolve(res); } ,function(err){ d.reject(err); });
return d.promise();
}
jQuery还提供了一个$.Deferred(fn)
表单,它的优点是允许我们编写一个模拟非常接近new Promise(fn)
表单的表达式,如下所示:
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
注意:这里我们利用了jQuery延迟的resolve
和reject
方法是“可拆卸”的事实; 即。 它们绑定到jQuery.Deferred()的实例。 并非所有库都提供此功能。
3.节点样式回调(“nodeback”):
节点样式回调(nodebacks)具有特殊的格式,其中回调总是最后一个参数,其第一个参数是错误。 我们先手动提示一个:
getStuff("dataParam",function(err,data){
至:
function getStuffAsync(param){
return new Promise(function(resolve,reject){
getStuff(param,function(err,data){
if(err !== null) return reject(err);
resolve(data);
});
});
}
使用延迟你可以做以下事情(让我们用Q代表这个例子,尽管Q现在支持你应该更喜欢的新语法):
function getStuffAsync(param){
var d = Q.defer();
getStuff(param,function(err,data){
if(err !== null) return d.reject(err); // `throw err` also works here.
d.resolve(data);
});
return d.promise;
}
一般来说,你不应该过多地手动提供这些东西,大多数承诺在Node中设计的库以及Node 8+中的本地promise都有一个内置的方法来提升nodeback。 例如
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4.具有节点样式回调的整个库:
这里没有黄金法则,你们一个一个的让步。 但是,有些承诺实现允许您批量执行此操作,例如在Bluebird中,将nodeback API转换为承诺API非常简单:
Promise.promisifyAll(API);
或者在Node中使用本地承诺:
const promiseAPI = Object.keys(API).map(key => {key, fn: util.promisify(API[key]))
.reduce((o, p) => Object.assign(o, {[p.key] : p.fn}), {});
笔记:
.then
处理你不需要promisify事情。 然后从一个处理者那里返回一个承诺.then
将会解决或拒绝承诺的价值。 从投掷.then
处理也是很好的做法,将拒绝承诺-这就是著名的承诺抛安全。 onload
情况下,您应该使用addEventListener
而不是onX
。 今天,我可以在Node.js
使用Promise
作为一个简单的Javascript方法。
Promise
一个简单而基本的例子(用KISS方式):
纯 Javascript Javascript异步API代码:
function divisionAPI (number, divider, successCallback, errorCallback) {
if (divider == 0) {
return errorCallback( new Error("Division by zero") )
}
successCallback( number / divider )
}
Promise
Javascript异步API代码:
function divisionAPI (number, divider) {
return new Promise(function (fulfilled, rejected) {
if (divider == 0) {
return rejected( new Error("Division by zero") )
}
fulfilled( number / divider )
})
}
(我建议访问这个美丽的来源)
还Promise
可以搭配在一起asyncawait
在ES7
使程序流程等待一个fullfiled
类似如下的结果:
function getName () {
return new Promise(function (fulfilled, rejected) {
var name = "John Doe";
// wait 3000 milliseconds before calling fulfilled() method
setTimeout (
function() {
fulfilled( name )
},
3000
)
})
}
async function foo () {
var name = await getName(); // awaits for a fulfilled result!
console.log(name); // the console writes "John Doe" after 3000 milliseconds
}
foo() // calling the foo() method to run the code
使用.then()
方法使用相同代码的另一种用法
function getName () {
return new Promise(function (fulfilled, rejected) {
var name = "John Doe";
// wait 3000 milliseconds before calling fulfilled() method
setTimeout (
function() {
fulfilled( name )
},
3000
)
})
}
// the console writes "John Doe" after 3000 milliseconds
getName().then(function(name){ console.log(name) })
Promise
也可以用于任何基于Node.js的平台,如react-native
。
希望这可以帮助。
我不认为@Benjamin的window.onload
建议会一直工作,因为它不检测它是否在加载后调用。 我被这么多次咬了。 这是一个应该始终工作的版本:
function promiseDOMready() {
return new Promise(function(resolve) {
if (document.readyState === "complete") return resolve();
document.addEventListener("DOMContentLoaded", resolve);
});
}
promiseDOMready().then(initOnLoad);
链接地址: http://www.djcxy.com/p/1627.html