[英]Understanding setTimeout and its implementation in JavaScript Promises
I have the following code:我有以下代码:
function MyPromise(configFunction) {
let nextSuccessCallBack = undefined;
let nextResolve = undefined;
configFunction(function(message){
setTimeout(function(){
if(nextSuccessCallBack) {
var result = nextSuccessCallBack(message);
if(result && result.then) {
result.then(nextResolve);
} else {
nextResolve && nextResolve(result);
}
}
})
});
return {
then: function(successCallback) {
nextSuccessCallBack = successCallback;
return new MyPromise(function(resolve) {
nextResolve = resolve;
})
}
}
}
new MyPromise(function(resolve, reject) {
resolve('new message');
}).then(function(message) {
console.log(message);
return 'another message'
}).then(function(message) {
console.log(message)
console.log('here')
})
In this example, it seems that the nextSuccessCallBack
is set to be the callback functions within .then
, then its value within the setTimeout function is now populated.在此示例中,似乎nextSuccessCallBack
设置为 .then 中的回调函数,然后填充 setTimeout .then
中的值。 However, this confuses me.然而,这让我很困惑。 I thought that when we reach the return
statement in the constructor, we return the object and effectively stop the function?我以为当我们到达构造函数中的return
语句时,我们返回object并有效地停止function? If that the case then how does the program even get to the setTimeout
?如果是这种情况,那么程序如何到达setTimeout
?
This is not a correct Promise implementation.这不是正确的 Promise 实现。 It clearly has no capabilities for rejections, but also for the implemented fulfilment feature it does not comply with the Promises/A+ specification .它显然没有拒绝的能力,而且对于实现的功能,它也不符合Promises/A+ 规范。 Just to give two examples:仅举两个例子:
It does not comply with rule 2.1.2.2不符合规则 2.1.2.2
When fulfilled, a promise must have a value, which must not change.完成后,promise 必须有一个值,该值不得更改。
....nor with rule 2.2.2.3: ....也不符合规则 2.2.2.3:
If
onFulfilled
is a function it must not be called more than once.如果onFulfilled
是 function,则不能多次调用它。
In your implementation, if you would add a second call to resolve
:在您的实现中,如果您要添加第二个调用来resolve
:
new MyPromise(function(resolve, reject) { resolve('new message'); resolve('new message2'); }).then((function(message) { console.log(message); //... etc })
...then both calls to resolve
would fire the then
callback, and show that the promised value was modified after the first time it was set. ...然后对resolve
的两个调用都会触发then
回调,并显示承诺的值在第一次设置后被修改。 This is in complete violation of the principle of promises: promises can only resolve once.这完全违反了 Promise 的原则:Promise 只能解决一次。
It does not comply with rule 2.2.6:它不符合规则 2.2.6:
then
may be called multiple times on the same promise.then
可以在同一个 promise 上多次调用。
- If/when
promise
is fulfilled, all respectiveonFulfilled
callbacks must execute in the order of their originating calls tothen
.如果/当promise
完成时,所有相应的onFulfilled
回调必须按照它们对then
的原始调用的顺序执行。
This does not happen if we use the following code:如果我们使用以下代码,则不会发生这种情况:
let p = new MyPromise(resolve => resolve("value")); p.then(console.log); // This callback is called p.then(console.log); // This callback is not called -> violation!
These are basic shortcomings, and this is just the tip of the iceberg.这些都是基本的缺点,而这只是冰山一角。
If you are interested in how it could be implemented in compliance with Promise/A+, then have a look at one I did a few years ago with a step-by-step explanation.如果您对如何按照 Promise/A+ 实施它感兴趣,那么请看一下我几年前所做的一步一步的解释。
how does the program even get to the
setTimeout
?程序甚至如何到达setTimeout
?
When your main code executes this:当您的主代码执行此操作时:
new MyPromise(function(resolve, reject) {
resolve('new message');
})
...then the parameter variable configFunction
is initialised with that callback function. ...然后使用该回调 function 初始化参数变量configFunction
。 The MyPromise
constructor calls it, passing it the following callback as first argument: MyPromise
构造函数调用它,将以下回调作为第一个参数传递给它:
function(message){
setTimeout(function(){
if(nextSuccessCallBack) {
var result = nextSuccessCallBack(message);
if(result && result.then) {
result.then(nextResolve);
} else {
nextResolve && nextResolve(result);
}
}
})
}
So that means that resolve
in your main code's callback function is initialised with the above callback function.所以这意味着在你的主代码的回调 function 中resolve
是用上面的回调 function 初始化的。 Then your main code's callback function calls resolve
with a string argument.然后您的主代码的回调 function 使用字符串参数调用resolve
。 Since resolve
is the above callback function, we can see it gets executed with message
initialised to "new message".由于resolve
是上述回调 function,我们可以看到它在message
初始化为“新消息”的情况下执行。 This function executes setTimeout
.这个 function 执行setTimeout
。
The code in the snippet does solve the purpose but, it is confusing as is a bad implementation of a Promise
according to the way MDN Uses Promises in JavaScript for better code efficiency and understanding.片段中的代码确实解决了这个目的,但是它令人困惑,因为根据MDN 在 JavaScript 中使用 Promises 以提高代码效率和理解的方式, Promise
的错误实现也是如此。
The above code can also be written this way:上面的代码也可以这样写:
const examplePromise = new Promise((resolve, reject) => {
resolve("Another Message");
});
console.log("New Message");
examplePromise.then((message) => {
console.log(message);
});
Now, for better understading of the concept of Promises in JavaScript, I'll take another example:现在,为了更好地理解 JavaScript 中 Promises 的概念,我再举一个例子:
Let's say I want to create a program which says hello and then after 2 seconds says How Are You?假设我想创建一个程序,它会说你好,然后在 2 秒后说你好吗?
There are two ways of solving this有两种方法可以解决这个问题
setTimeout()
function which executes a function after certain period of time只需使用setTimeout()
function 在一段时间后执行 functionsetTimeout()
通过setTimeout()
使用 PromiseCase I (Using setTimeout() ):案例一(使用setTimeout() ):
console.log("hello"); //Saying hello for the first time
setTimeout(function () {
console.log("How Are You?");
}, 2000); //2000 milliseconds is 2 seconds
Case II (Using Promises )案例二(使用承诺)
console.log("hello");
const example = new Promise((resolve) => {
setTimeout(() => {
resolve("How Are You?");
}, 2000);
});
example.then((message) => {
console.log(message);
});
Now, for simple cases like logging a message after 2 seconds do not require Promises .现在,对于简单的情况,例如 2 秒后记录一条消息,不需要 Promises 。 You may use them (No problem) but actually, Promises
are used in cases where, you wait for a function to execute a Database Query or you need to wait for a server to give you some HTML Response or while using WebAPIs, etc.您可以使用它们(没问题),但实际上,Promise 用于以下情况:您等待Promises
执行数据库查询,或者您需要等待服务器给您一些 HTML 响应或使用 WebAPI 等。
PS: setTimeout()
is just an example. PS: setTimeout()
只是一个例子。 It is not a rule that you always have to use setTimeout()
while writing a Promise
.在编写Promise
时,并非总是必须使用setTimeout()
。 If you are fetching data using a WebAPI, you usually write $.ajax(...).then(...)
or fetch(...).then(...)
instead of setTimeout()
如果您使用 WebAPI 获取数据,您通常编写$.ajax(...).then(...)
或fetch(...).then(...)
而不是setTimeout()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.