Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/370.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
Javascript承诺不会按预期工作_Javascript_Typescript_Promise_Es6 Promise_Nonblocking - Fatal编程技术网

Javascript承诺不会按预期工作

Javascript承诺不会按预期工作,javascript,typescript,promise,es6-promise,nonblocking,Javascript,Typescript,Promise,Es6 Promise,Nonblocking,大家好,我正在努力理解javascript中承诺的概念。我已经编写了这个非常简单的程序来实现这一点。但是我得到的输出顺序并不是我期望的。我期望输出顺序是: 在func之后 外面的一切 0 0 495510 496506 497503 498501 但我得到的是相反的结果。我希望得到上面的输出,因为代码应该是非阻塞的,因为我使用的是Promise。因此程序应该继续执行。但是从实际的输出来看,我得到的结果似乎是调用func()后代码阻塞了代码。我在这里做错了什么?我应该改变什么以获得所需的输出,我在

大家好,我正在努力理解javascript中承诺的概念。我已经编写了这个非常简单的程序来实现这一点。但是我得到的输出顺序并不是我期望的。我期望输出顺序是:

在func之后

外面的一切

0

0

495510

496506

497503

498501

但我得到的是相反的结果。我希望得到上面的输出,因为代码应该是非阻塞的,因为我使用的是Promise。因此程序应该继续执行。但是从实际的输出来看,我得到的结果似乎是调用func()后代码阻塞了代码。我在这里做错了什么?我应该改变什么以获得所需的输出,我在这里遗漏了什么?下面是代码,上面附有一个屏幕截图

function func() {
    return new Promise((resolve,reject)=>{
    for(var i=0;i<1000;i++){
        console.log(sum)
        sum+=i;
    }
    if(sum>200){
    resolve("Greater than ")
    }
    else{
        reject("Error:")
    }
})}
async function somefunction(){
    func()
    console.log("after func")
}
somefunction()
console.log("Outside everything")
函数func(){
返回新承诺((解决、拒绝)=>{
对于(变量i=0;i200){
决心(“大于”)
}
否则{
拒绝(“错误:”)
}
})}
异步函数somefunction(){
func()
console.log(“在func之后”)
}
somefunction()
console.log(“外部一切”)

异步函数和承诺在函数完成之前返回

以下是您的代码的固定版本:

function func() {
    return new Promise((resolve,reject)=>{
    for(var i=0;i<1000;i++){
        console.log(sum)
        sum+=i;
    }
    if(sum>200){
    resolve("Greater than ")
    }
    else{
        reject("Error:")
    }
})}
async function somefunction(){
    func()
    console.log("after func")
}
somefunction().then(() => {
    console.log("Outside everything")
})
函数func(){
返回新承诺((解决、拒绝)=>{
对于(变量i=0;i200){
决心(“大于”)
}
否则{
拒绝(“错误:”)
}
})}
异步函数somefunction(){
func()
console.log(“在func之后”)
}
somefunction()。然后(()=>{
console.log(“外部一切”)
})

这可能就是它的外观

(async () => {
  // Using IIFE (immediately invoked function expression) as somefunction is async
  // But this is optional 
  function func () {
    return new Promise((resolve,reject) => {
      // add sum variable
      let sum = 0
      for (let i = 0;i < 10;i++) { // for simplicity using 10
        sum += i
        console.log(sum)
      }
      if (sum > 5) {  // for simplicity using 5
        resolve('Greater than ')
      } else {
        reject('Error:')
      }
    })
  }
  async function somefunction () {
    try {
      // await func to be resolved
      const result = await func() // get result from resolve call
      console.log(result)
    } catch (e) {
      console.log(e) // get result from reject call
    }
    console.log('after func')
  }
  // wait until somefunction finishes, its necessary to void console.log('Outside everything') being called immediately
  await somefunction() 
  console.log('Outside everything')
})()

这里需要理解的关键是,承诺始终保证在当前运行(即当前执行块)结束时得到解决,即使它们看起来是“立即”解决的。即:

Promise.resolve().then(() => console.log('a'));
console.log('b'); //"b", "a" - NOT "a", "b"
(进一步阅读:我在《承诺指南》的第三部分中详细讨论了这一概念。)

记住这一点,让我们看看发生了什么

首先调用
func()
。不要被它前面的
async
所迷惑;它仍然是一个同步函数调用,因此它的操作首先发生
async
只是作为一个“提示”,它的主体将执行异步操作,而不是它本身是异步的

这些操作中的第一个涉及承诺,因此基于上述内容,我们知道它们将在同步
console.log()之后最后解决。当这些操作被推到队列的后面时,我们转到第二个操作,即输出“after func”

这是函数的结尾,因此执行流返回到该函数的调用者范围。它发现接下来要做的事情是“在一切之外”输出


这就是执行流程的结束(“记住,当前运行”),因此承诺(数字)现在可以自由解析和输出。

为什么会有
async
?这并没有给脚本添加任何有用的内容。是的,这是因为如果需要的话,我会在func()语句之前使用wait。我只是在这里尝试不同的方法来更好地理解这个概念。在这个演示中,我删除了func()前面的wait。“代码应该是非阻塞的,因为我使用的是Promise”-不。当代码使用一些本机异步内容(如超时)时,它是非阻塞的,但您的代码不是。
newpromise
构造函数不做任何非阻塞的东西,它提供的输出与我的案例(在屏幕截图中)完全相同。这也不是我想要的。我完全理解你做了什么,因为我习惯了用这种方式使用承诺(如你所示)。但这不是我想要的。我想在屏幕上首先或第二次打印外部的所有内容。就像非阻塞代码一样,不需要使用wait here。谢谢。我在func()中添加了console.log(),因为我试图模拟func()中的某个任务。该任务将需要一些时间。而当该任务在func()中进行时,我们的主程序将继续执行它自己的工作。这就是为什么我希望外部的所有内容都首先或第二次打印,然后从func()内部打印所有的console.log()。有办法吗?也就是说,当func()内部正在进行一些繁重的计算时,程序中的所有其他内容都会随之进行,而不是在func()完成之后。
Promise.resolve().then(() => console.log('a'));
console.log('b'); //"b", "a" - NOT "a", "b"