我是Java和Promise的新手。我可以理解Promise何时立即具有on子句,如下:
//example 1
var promise1 = new Promise(function(resolve, reject) {
console.log("Hi")
resolve("World")
}).then(function(value) {
console.log(value);
});
但是如果then
子句在单独的语句中为:
//example 2
var promise1 = new Promise(function(resolve, reject) {
console.log("Hi")
resolve("World")
});
//at time t here
promise1.then(function(value) {
console.log(value);
});
console.log("Hello");
那我有点困惑,因为从技术上讲,时间t之前的语句已经执行,并且当resolve("World")
被调用时,因为没有then
子句被“注册”,所以什么也不会发生。在时间t之后,promise1.then(...)
执行,并且它不应该知道已经调用了resolve("World")
。但是实际输出确实表明它知道resolve("World")
已被调用。
那么这是否意味着编译器确实在此提供帮助?例如,编译器像示例1一样在promise1语句之后合并then
子句?
答案 0 :(得分:3)
这是因为Promise对象在内部保持其状态。
因此,当您在Promise对象上调用.then
时,它将:
答案 1 :(得分:1)
那么这是否意味着编译器确实在此提供帮助?例如,编译器像示例1一样在promise1语句之后合并then子句?
不,发生的魔术比您想象的要少得多。 new Promise
返回一个Promise对象。一个Promise对象有一个.then
方法。您可以使用此方法告诉一旦被解决的承诺,调用传递的函数。 Promise对象会保留此回调。
您可以将其视为注册事件处理程序。一旦发生“解决事件”,该函数就会执行。
当然,承诺者会知道它是否已解决。因此,如果在已解决的Promise上调用.then
,它可以立即安排回调的调用。
这是一个非常贫穷的人对诺言的执行(不处理拒绝和其他事情),这可能使您更好地了解诺言的工作方式。请注意,我在这里使用setTimeout
来模拟promise如何总是在event loop的下一个滴答处执行回调,但是实际上JavaScript使用了其他一些内部API:
class Promise {
constructor(handler) {
this._callbacks = [];
// Execute the passed handler, passing the "resolve" function
handler(value => {
// Mark the promise as resolved
this._resolved = true;
// Remember the value
this._value = value;
// Execute all registered callbacks
this._callbacks.forEach(cb => cb(value));
});
}
then(handler) {
let _resolve;
const promise = new Promise(resolve => _resolve = resolve);
const callback = value => {
setTimeout(
() => _resolve(handler(value)),
0
);
};
// Is the promise already resolved?
if (this._resolved) {
// Immediately schedule invocation of handler with the remembered value
callback(this._value);
} else {
// Remember callback for future invocation
this._callbacks.push(callback);
}
return promise;
}
}
const promise = new Promise(resolve => {
console.log('inside Promise');
resolve(42);
});
console.log('in between');
promise.then(v => {
console.log('inside then', v);
})
promise.then(v => {
console.log('inside another then', v);
return 21;
})
.then(v => {
console.log('.then returns a new promise', v);
});