您要求theContent
直线(程序)而不是回调的部分。
.done(function (content) { doStuff(content); });
或者,如果doStuff
不使用this
并且您不需要对它执行任何其他操作,那么.done(doStuff);
当内容返回时,将与内容一起触发 just 和 doStuff。
loadImage = function () {}; // returns promise
showImage = function (image) {} // shows image
var imageLoading = loadImage("img/huge-img.bmp");
imageLoading.done(showImage);
或者为了更简洁,构建showImage
使用 Promise(在函数内部订阅它们的回调)。
function showImage(promise) {
promise.done(function (img) {
document.body.appendChild(image);
});
现在你有
var image = loadImage("huge-img.bmp");
showImage(image);
使用承诺。看起来完全自然。
编辑 重新:命名空间
您可能仍然不希望将事物推入列表作为您在回调中所做的唯一事情。
什么在使用列表?
是theList.push()
一个自定义函数,它具有相同的名称,[].push()
但有额外的东西吗?
还是只是一堆东西?
这就是问题所在:
就像 AJAX 回调一样,promise 不会等待事情完成,然后再继续下一件事情。
因此,如果您的程序试图在该数组之外done
(当数组最终有数据时)对该数组执行某些操作,那么这些函数将在一个空数组上工作。
相反,您应该使用方法(回调)来处理 Promise 的返回。
// these both do the same thing
/* ... */ .done(function (data) { NAMESPACE.module.callback(data); });
/* ... */ .done(NAMESPACE.Module.callback.bind(NAMESPACE.Module));
// if NAMESPACE.Module.callback ***does not use `this`*** you can write
/* ... */ .done(NAMESPACE.Module.callback);
// if you are unsure for even a second, do one of the other two calls
如果您需要对回调中的数据做更多的事情,那么只需执行以下操作:
/* ... */ .done(function (data) {
var arr = doStuff(data);
arr.forEach(function (obj) {
NAMESPACE.Module.list.push(obj);
});
NAMESPACE.Module.callback_relying_on_list();
});
请注意,这里的 2 个键是:
- 确保
this
你的回调是正确的
- 在承诺范围内工作——它们的重点是让你不必设置计时器来查看东西是否准备好了,但是......所以如果你只是设置值而不告诉任何人他们已经准备好了准备好了,承诺没有发挥作用
编辑#2 回复:来源
看看你在这里做什么(简化):
// a.js
function getFiles () {
GLOBAL.list = [];
getAsyncData().done(function (text) {
GLOBAL.list.push({ content : text });
});
}
//b.js
GLOBAL.Messages = {
write : function (messages) {
messages.forEach(/* ... */);
},
ready : function () { alert(GLOBAL.list.length); } }
};
// main program
getFiles();
GLOBAL.Messages.ready();
GLOBAL.Messages.write(GLOBAL.list);
我知道这不是您的确切代码,但请看一下简化的情况:
如果我的getFiles
功能完美运行,但服务器在 30 秒内没有发回我的数据,会发生什么情况?
我的ready
和write
函数不会等待这种情况发生。我一做完
他们就会开火。getFiles
所以在这里,你在错误的地方得到了这个承诺。
这是 100% 正确的方法,但为什么不这样做:
// a.js
function getFiles () {
var filesLoaded = getAsyncData(); // I'm collecting the promise, not chaining it.
// again, simplified
filesLoaded.done(function (text) { GLOBAL.list.push({ content : text}); });
// ***super important part***
return filesLoaded;
}
// b.js
/* ... */ = {
ready : function (promise) {
promise.done(function () { alert(GLOBAL.list.length); });
},
write : function (promise) {
promise.done(/* write the list */);
}
}
现在你的主要看起来像这样:
var files = getFiles(); // files is the promise
// files.done, files.then, etc
GLOBAL.Messages.ready(files); // giving the promise to the method
// ready(promise) will subscribe to promise.done
GLOBAL.messages.write(files); // so will write(promise);
以这种方式使用 Promise 时,请记住,我的示例与您添加到链中的 files
对象完全相同。.done()
还要记住,有时你的函数会关心 promise 返回的值,而其他时候,函数只想知道 promise 何时完成,因此它们可以做一些事后需要发生的事情,而不是设置计时器来检查.
并且在您处理同步数据的任何时候都可以使用已清理的功能,现在您可以:
var files = readTextFromFiles();
/* ... */.ready(promise);
这是否意味着您需要一个更多的功能来介于它ready
正在做什么和您的旧准备看起来像之间?
嗯,是的……
但是值得知道您的功能不会过早关闭。
它看起来非常干净,没有巢穴,同时仍然是 100% 同步的。
如果你赶时间,或者你不能编辑那些其他功能,你可能会做一个坏主意,那就是在页面底部引导一些东西:
(function (promise) { promise.done(function () {
/* ... everything() ... */ });
}(files));
丑陋且难以区分,需要在单独的页面上进行编辑,但至少它仍然是异步的,它仍然按顺序做事。
但这仍然意味着返回、收集和传递承诺。
希望有帮助。