将 Deferred 添加到非异步函数
Adding a Deferred to a non async function
我目前正在开发一个需要很长时间才能完成的函数,因为我无法让它更快地完成,我打算从其他脚本中调用它,我想知道是否有在该函数中使用类似 promise 的方法。
基本上
function longrunning(){
var def = new $.Deferred();
var result = {};
[DO STUFF THAT TAKES A WHILE]
def.resolve();
return def.promise(result);
}
我的基本问题是,由于所有正在进行的事情都不是异步的,所以我的承诺在所有事情都完成之前不会 returned,所以稍后将调用 longrunning 的函数不会'不知道它是异步的。但是当然,如果我 return 在执行所有代码之前承诺,它根本不会解决。我希望你得到我正在努力做的事情。希望有人有想法。在此先感谢
你好,克里斯
将代码包装在 $.Deferred
(或本机承诺)中将无济于事,即使您在执行 long-running 工作之前设法将承诺返回给调用代码(例如, 通过 setTimeout
).它所能完成的就是让主 UI 线程在 之后 ,在 longrunning
return 承诺后不久,而不是在调用 longrunning
本身。所以,没有用。 :-)
如果有问题的函数不操纵 DOM,或者如果它所做的操纵可以从 long-running 逻辑中分离出来,那么这是一个很好的候选者,可以移动到 web worker (specification, MDN),所以它根本不会在主 UI 线程上获得 运行,而是获得 运行在并行工作线程中,让 UI 自由地继续响应。
longrunning
不会做实际的工作,它只会 postMessage
工作人员要求它做工作,然后在它返回一条工作消息时解决你的承诺已经完成了。沿着这些方向的东西(这只是一个代码草图,不是 fully-implemented 解决方案):
var pendingWork = {};
var workId = 0;
var worker = new Worker("path/to/web/worker.js");
worker.addEventListener("message", function(e) {
// Worker has finished some work, resolve the Deferred
var d = pendingWork[e.data.id];
if (!d) {
console.error("Got result for work ID " + e.data.id + " but no pending entry for it was found.");
} else {
if (e.data.success) {
d.resolve(e.data.result);
} else {
d.reject(e.data.error);
}
delete pendingWork[e.data.id];
}
});
function longrunning(info) {
// Get an identifier for this work
var id = ++workid;
var d = pendingWork[id] = $.Deferred();
worker.postMessage({id: id, info: info});
return d.promise();
}
(假定工作人员发回的是一个具有属性 id
[工作 ID]、success
[标志] 和 result
[结果] 的对象或 error
[错误]。)
如您所见,我们 longrunning
将工作发送给工作人员,并 return 对它的承诺;当工作人员发回工作时,侦听器会解析 Deferred。
如果 long-running 任务 确实 需要进行 DOM 操作作为其工作的一部分,它可以 post 返回必要的信息到主脚本,让它在必要时代表它进行这些操作。它的可行性自然取决于代码在做什么。
当然,如果您只需要在 up-to-date 浏览器上 运行(或包含一个 polyfill),您可以使用本机承诺而不是 jQuery 的 $.Deferred
:
var pendingWork = {};
var workId = 0;
var worker = new Worker("path/to/web/worker.js");
worker.addEventListener("message", function(e) {
// Worker has finished some work, resolve the Deferred
var work = pendingWork[e.data.id];
if (!work) {
console.error("Got result for work ID " + e.data.id + " but no pending entry for it was found.");
} else {
if (e.data.success) {
work.resolve(e.data.result);
} else {
work.reject(e.data.error);
}
delete pendingWork[e.data.id];
}
});
function longrunning(info) {
return new Promise(function(resolve, reject) {
// Get an identifier for this work
var id = ++workid;
pendingWork[id] = {resolve: resolve, reject: reject};
worker.postMessage({id: id, info: info});
});
}
我目前正在开发一个需要很长时间才能完成的函数,因为我无法让它更快地完成,我打算从其他脚本中调用它,我想知道是否有在该函数中使用类似 promise 的方法。
基本上
function longrunning(){
var def = new $.Deferred();
var result = {};
[DO STUFF THAT TAKES A WHILE]
def.resolve();
return def.promise(result);
}
我的基本问题是,由于所有正在进行的事情都不是异步的,所以我的承诺在所有事情都完成之前不会 returned,所以稍后将调用 longrunning 的函数不会'不知道它是异步的。但是当然,如果我 return 在执行所有代码之前承诺,它根本不会解决。我希望你得到我正在努力做的事情。希望有人有想法。在此先感谢
你好,克里斯
将代码包装在 $.Deferred
(或本机承诺)中将无济于事,即使您在执行 long-running 工作之前设法将承诺返回给调用代码(例如, 通过 setTimeout
).它所能完成的就是让主 UI 线程在 之后 ,在 longrunning
return 承诺后不久,而不是在调用 longrunning
本身。所以,没有用。 :-)
如果有问题的函数不操纵 DOM,或者如果它所做的操纵可以从 long-running 逻辑中分离出来,那么这是一个很好的候选者,可以移动到 web worker (specification, MDN),所以它根本不会在主 UI 线程上获得 运行,而是获得 运行在并行工作线程中,让 UI 自由地继续响应。
longrunning
不会做实际的工作,它只会 postMessage
工作人员要求它做工作,然后在它返回一条工作消息时解决你的承诺已经完成了。沿着这些方向的东西(这只是一个代码草图,不是 fully-implemented 解决方案):
var pendingWork = {};
var workId = 0;
var worker = new Worker("path/to/web/worker.js");
worker.addEventListener("message", function(e) {
// Worker has finished some work, resolve the Deferred
var d = pendingWork[e.data.id];
if (!d) {
console.error("Got result for work ID " + e.data.id + " but no pending entry for it was found.");
} else {
if (e.data.success) {
d.resolve(e.data.result);
} else {
d.reject(e.data.error);
}
delete pendingWork[e.data.id];
}
});
function longrunning(info) {
// Get an identifier for this work
var id = ++workid;
var d = pendingWork[id] = $.Deferred();
worker.postMessage({id: id, info: info});
return d.promise();
}
(假定工作人员发回的是一个具有属性 id
[工作 ID]、success
[标志] 和 result
[结果] 的对象或 error
[错误]。)
如您所见,我们 longrunning
将工作发送给工作人员,并 return 对它的承诺;当工作人员发回工作时,侦听器会解析 Deferred。
如果 long-running 任务 确实 需要进行 DOM 操作作为其工作的一部分,它可以 post 返回必要的信息到主脚本,让它在必要时代表它进行这些操作。它的可行性自然取决于代码在做什么。
当然,如果您只需要在 up-to-date 浏览器上 运行(或包含一个 polyfill),您可以使用本机承诺而不是 jQuery 的 $.Deferred
:
var pendingWork = {};
var workId = 0;
var worker = new Worker("path/to/web/worker.js");
worker.addEventListener("message", function(e) {
// Worker has finished some work, resolve the Deferred
var work = pendingWork[e.data.id];
if (!work) {
console.error("Got result for work ID " + e.data.id + " but no pending entry for it was found.");
} else {
if (e.data.success) {
work.resolve(e.data.result);
} else {
work.reject(e.data.error);
}
delete pendingWork[e.data.id];
}
});
function longrunning(info) {
return new Promise(function(resolve, reject) {
// Get an identifier for this work
var id = ++workid;
pendingWork[id] = {resolve: resolve, reject: reject};
worker.postMessage({id: id, info: info});
});
}