如何在没有异步/等待的情况下从待解决的承诺中获取数据?

kar*_*017 8 javascript promise

我有抽象:

\n\n
function fetchDataFromAPI() {\n  const url = `https://api...`\n  return fetch(url).then(response => response.json())\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想在我的其他代码中使用它,例如:

\n\n
if(something){\n  const data = fetchDataFromAPI()\n  return data \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我的console.log数据得到解决,等待承诺

\n\n
Promise\xc2\xa0{<pending>}\n  __proto__: Promise\n  [[PromiseStatus]]: "resolved"\n  [[PromiseValue]]: Object\n
Run Code Online (Sandbox Code Playgroud)\n\n

我如何获取该对象data而不是 Promise?

\n

snn*_*snn 11

You can not. Here is why:

Promise is a language construct that makes JavaScript engine to continue to execute the code without waiting the return of inner function, also known as the executor function. A promise always run inside the event loop.

var p = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

console.log(p);
Run Code Online (Sandbox Code Playgroud)

Basically a promise is a glorified syntactic sugar for a callback. We will see how but first lets have a more realistic code:

function someApiCall(){
  return new Promise(function(resolve, reject){
    setTimeout(()=>{
      resolve('Hello');
    })
  })
}

let data = someApiCall();

console.log(data);
Run Code Online (Sandbox Code Playgroud)

This is a so-called asynchronous code, when JavaScript engine executes it, someApiCall immediately returns a result, in this case pending promise:

> Promise {<pending>}
Run Code Online (Sandbox Code Playgroud)

If you pay attention to the executor, you will see we needed to pass resolve and reject arguments aka callbacks. Yes, they are callbacks required by the language construct. When either of them called, promise will change its state and hence be settled. We don't call it resolved because resolving implies successful execution but a function also can error out.

How do we get the data? Well we need more callbacks, which will be called by the executor function once the promise is settled:

var p = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

p.then((result) => {
  console.log(result); // foo
}).catch((err) => {
  console.log(err);
});
Run Code Online (Sandbox Code Playgroud)

Why we need to pass separate callbacks? Because one will be fed to the resolve, and the other to the reject. Then callback will be called by the resolve function, the catch callback by the reject function.

Javascript engine will execute these callbacks later on its leisure, for a regular function it means when the event loop is cleared, for timeout when the time is up.

Now to answer your question, how do we get data out from a promise. Well we can't.

If you look closely, you will see we don't really get the data out but keep feeding callbacks. There is no getting data out, but passing callbacks in.

p.then((result) => {
  console.log(result);
}).catch((err) => {
  console.log(err);
});
Run Code Online (Sandbox Code Playgroud)

有人说使用等待:

async function() {
  let result = await p;
}
Run Code Online (Sandbox Code Playgroud)

但是有一个问题!我们必须将其包装在异步函数中。总是。为什么?因为 Async/await 是 Promise api 之上的另一个抽象或语法糖级别,无论您喜欢哪种。这就是为什么我们不能直接使用await而是总是将其包装在async语句中。

总而言之,当我们使用 Promise 或 async/await 时,我们需要遵循一定的约定并编写简洁的代码和紧密结合的回调。javascript 引擎或像 babeljs 或 typescript 这样的转译器将这些代码转换为要运行的常规 javascript。

我可以理解您的困惑,因为人们在谈论承诺时一直说获取数据,但我们没有获取任何数据,而是传递回调以在数据准备好时执行。

希望现在一切都清楚了。