Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解setTimeout及其在JavaScript中的实现_Javascript_Promise_Settimeout_Es6 Promise - Fatal编程技术网

理解setTimeout及其在JavaScript中的实现

理解setTimeout及其在JavaScript中的实现,javascript,promise,settimeout,es6-promise,Javascript,Promise,Settimeout,Es6 Promise,我有以下代码: function MyPromise(configFunction) { let nextSuccessCallBack = undefined; let nextResolve = undefined; configFunction(function(message){ setTimeout(function(){ if(nextSuccessCallBack) { var result = nextSuccessCallBack

我有以下代码:

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')
})
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!

在本例中,
nextSuccessCallBack
似乎被设置为
中的回调函数。然后
,然后它在setTimeout函数中的值现在被填充。然而,这让我感到困惑。我认为当我们到达构造函数中的
return
语句时,我们返回对象并有效地停止函数?如果是这样的话,那么程序是如何到达
设置超时的呢?

代码片段中的代码确实解决了这个问题,但是,按照更好的代码效率和理解方式,它是一个混乱的
承诺的糟糕实现

上述代码也可以这样编写:

const examplePromise = new Promise((resolve, reject) => {
    resolve("Another Message");
});

console.log("New Message");
examplePromise.then((message) => {
    console.log(message);
});
现在,为了更好地理解JavaScript中承诺的概念,我将举另一个例子:

假设我想创建一个程序,它会说你好,然后在2秒钟后说你好吗?

有两种方法可以解决这个问题

  • 只需使用
    setTimeout()
    函数,该函数在一定时间后执行函数
  • 使用带有
    setTimeout()的承诺
案例一(使用):

案例二(使用)

现在,对于简单的情况,如在2秒后记录消息,不需要承诺。您可以使用它们(没问题),但实际上,
承诺
用于以下情况:等待函数执行数据库查询,或者需要等待服务器给您一些HTML响应,或者在使用WebAPI时,等等


注:
setTimeout()
只是一个例子。
在编写
承诺时,您不必总是使用
setTimeout()
。如果使用WebAPI获取数据,通常会编写
$.ajax(…)。然后(…)
获取(…)。然后(…)
而不是
设置超时()

,这不是正确的Promise实现。它显然没有拒绝功能,但也没有实现它不符合的实现功能。举两个例子:

  • 它不符合规则2.1.2.2

    履行承诺时,承诺必须有一个价值,这个价值不能改变

    ..也不适用规则2.2.2.3:

    如果
    oncompleted
    是一个函数,则不能多次调用它

    在实现中,如果要添加第二个对
    resolve
    的调用:

    new MyPromise(function(resolve, reject) {
      resolve('new message'); resolve('new message2');
    }).then((function(message) {
      console.log(message);
      // ... etc
    })
    
    …然后对
    resolve
    的两个调用都将触发
    then
    回调,并显示承诺的值在第一次设置后已被修改。这完全违反了承诺的原则:承诺只能解决一次

  • 它不符合规则2.2.6:

    可能会在同一承诺上被多次调用

    • 如果履行了
      承诺
      ,则所有相应的
      oncompleted
      回调必须按照其对
      的原始调用的顺序执行,然后
    如果我们使用以下代码,则不会发生这种情况:

    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')
    })
    
    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!
    
  • 这些都是基本的缺点,这只是冰山一角

    如果您对如何按照Promise/A+实现它感兴趣,那么请看一看逐步的解释

    至于你的问题 程序是如何到达设置超时的

    当主代码执行此操作时:

    new MyPromise(function(resolve, reject) {
      resolve('new message');
    })
    

    …然后使用该回调函数初始化参数变量
    configFunction
    MyPromise
    构造函数调用它,并将以下回调作为第一个参数传递给它:

      function(message){
        setTimeout(function(){
          if(nextSuccessCallBack) {
            var result = nextSuccessCallBack(message);
            if(result && result.then) {
              result.then(nextResolve);
            } else {
              nextResolve && nextResolve(result);
            }
          }
        })
      }
    

    这意味着主代码的回调函数中的
    resolve
    是用上述回调函数初始化的。然后,主代码的回调函数使用字符串参数调用
    resolve
    。由于
    resolve
    是上面的回调函数,我们可以看到它是在
    message
    初始化为“newmessage”的情况下执行的。此函数执行
    setTimeout

    configFunction
    被调用(这是传递到MyPromise的回调),调用
    resolve
    (这是传递到
    configFunction
    的回调),调用
    setTimeout
    。这是一个非常糟糕的
    Promise
    实现。我一点也不像真正的promise那样工作。“JavaScript编程指南”是什么?另外,我认为OP是想理解他们的算法为什么不起作用,而不是如何使用本地算法……它不会丢失,或者?你可以起草你的问题/答案,只要你想,它不会丢失。因此也会将其保存到本地存储。。。