J. *_*rsh 0 javascript asynchronous node.js promise jquery-deferred
我发现各种Deferred/promise库的文档通常涵盖非常简单的用例,例如链接1或2个函数/方法,并导致解决或拒绝成功或错误.
然而,当涉及到更复杂的用例(5个以上的函数/方法链;嵌套的Deferreds;从其他Deferreds中返回promise)时,我空手而归并变得非常沮丧.
比方说,我有一个包含2个嵌套函数的函数.每个子函数都返回一个promise,我希望父函数返回子函数的成功/失败结果:
var saveUser = function(user) {
var saveNewUser = function(user) {
var deferred = when.defer();
user.save(function (err) {
if (err) {
deferred.reject();
}
else {
// forcing a rejection here for testing purposes
deferred.reject(6);
}
});
return deferred.promise;
}
var supplyUserCollections = function() {
var deferred = when.defer();
deferred.reject();
return deferred.promise;
}
return saveNewUser(user).then(supplyUserCollections(), function() {
console.log('failed to save new user');
}).then(function(data) {
console.log('succeeded to do everything');
}, function() {
console.log('failed to seed new user collections');
});
}
Run Code Online (Sandbox Code Playgroud)
这不起作用; 奇怪的是,"成功地做了一切" console.log火灾,即使我强迫拒绝/失败两个孩子的功能.看作是a的第一个参数.then是成功案例,我真的不明白为什么会这样.此外,假设父函数saveUser是另一个广泛的承诺链的一部分,如下所示:
dropExistingCollections(collections).then(saveEntities(albums), function() {
console.log('failed to drop existing collections');
}).then(saveEntities(movies), function() {
console.log('failed to save all albums');
}).then(saveEntities(games), function() {
console.log('failed to save all movies');
}).then(saveUsers(users), function() {
console.log('failed to save all games');
}).then(function(data) {
console.log(data);
console.log('successfully saved all seed data');
res.send('database data wiped and re-seeded');
}, function() {
console.log('failed to save all users');
});
Run Code Online (Sandbox Code Playgroud)
我不确定如何以一种saveUser可与其余函数链接的方式正确地返回一个promise ,这些函数都是返回已解析/拒绝Deferred的简单函数.
我真的只是想更确切地说明如何处理延迟/承诺的一些更复杂的用例.这显然是一个非常密集的话题,我发现的大多数材料并没有与我产生特别好的共鸣.
始终从同步代码开始.它更容易理解,并且异步代码的转换从未如此困难.如果您已经包含了编写同步代码的方式,而不仅仅是一些稍微破坏的异步代码,那么我可以更轻松地找出您希望代码执行的操作.
您最初的问题可能只是您在不想要的地方添加了括号.您应始终将函数传递给then处理程序:
return saveNewUser(user).then(supplyUserCollections /* NOTE: no parenthesis */, function() {
console.log('failed to save new user');
}).then(function(data) {
console.log('succeeded to do everything');
}, function() {
console.log('failed to seed new user collections');
});
Run Code Online (Sandbox Code Playgroud)
这似乎是你对第二个功能的关键误解.
想象一下,您想要编写的代码可能看起来像下面这样(如果用户有saveSync方法和save方法).
function saveNewUser(user) {
var result = user.saveSync();//may throw
// forcing a throw here for testing purposes
throw 6;
}
function supplyUserCollections() {
throw new Error('failed supplyUserCollections');
}
function saveUser(user) {
try {
saveNewUser(user);
} catch (ex) {
console.log('failed to save new user');
return;
}
try {
supplyUserCollections();
} catch (ex) {
console.log('failed to seed new user collections');
return;
}
console.log('succeeded to do everything');
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以转换saveNewUser和supplyUserCollections非常简单:
function saveNewUser(user) {
var deferred = when.defer();
user.save(function (err) {
if (err) {
deferred.reject();
}
else {
// forcing a rejection here for testing purposes
deferred.reject(6);
}
});
return deferred.promise;
}
function supplyUserCollections() {
var deferred = when.defer();
deferred.reject();
return deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)
完成此操作后,我们只需要转换更复杂的saveUser方法:
function saveUser(user) {
saveNewUser(user)
.then(function () {
//this only happens if `saveNewUser` succeeded, like the bit after
//a catch block containing a `return`
return supplyUserCollections()
.then(function () {
console.log('succeeded to do everything');
}, function (ex) {
console.log('failed to seed new user collections');
})
}, function (ex) {
//this happens when `saveNewUser` failed (just like the catch block)
console.log('failed to save new user');
})
}
Run Code Online (Sandbox Code Playgroud)
现在在我看来,更可能的同步函数版本可能是这样的:
function saveUser(user) {
saveNewUser(user);
supplyUserCollections();
console.log('succeeded to do everything');
}
Run Code Online (Sandbox Code Playgroud)
您可以写为:
function saveUser(user) {
saveNewUser(user)
.then(function () {
//this only happens if `saveNewUser` succeeded
return supplyUserCollections()
})
.then(function () {
//this happens when both methods succeeded
console.log('succeeded to do everything');
})
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
828 次 |
| 最近记录: |