异步函数不返回值,但是console.log()可以:怎么办?

我有一个es6类,该类init()负责获取数据,对其进行转换,然后this.data使用新转换的数据更新该类的属性。到现在为止还挺好。类本身还有另一种getPostById()方法,可以按照听起来的方式进行操作。这是该类的代码:

class Posts {

constructor(url) {

this.ready = false

this.data = {}

this.url = url

}

async init() {

try {

let res = await fetch( this.url )

if (res.ok) {

let data = await res.json()

// Do bunch of transformation stuff here

this.data = data

this.ready = true

return data

}

}

catch (e) {

console.log(e)

}

}

getPostById(id){

return this.data.find( p => p.id === id )

}

}

简单来说,除了我async/awaitinit()方法中有一个机制。现在,此代码将正常运行:

let allPosts = new Posts('https://jsonplaceholder.typicode.com/posts')

allPosts.init()

.then( d => console.log(allPosts.getPostById(4)) )

// resulting Object correctly logged in console

但是它只能打印到控制台中:如何将它allPosts.getPostById(4)用作return功能?

喜欢:

let myFunc = async () => {

const postId = 4

await allPosts.init() // I need to wait for this to finish before returning

// This is logging correct value

console.log( 'logging: ' + JSON.stringify(allPosts.getPostById( postId ), null, 4) )

// How can I return the RESULT of allPosts.getPostById( postId ) ???

return allPosts.getPostById( postId )

}

myFunc()返回一个Promise但不是最终值。我已经阅读了有关此主题的几篇相关文章,但它们都提供了日志记录示例,从此不再返回。

这是一个jsfiddle,其中包括两种处理方式init():使用Promise和使用async/await。无论我做什么,我都无法使用的最终值getPostById(id)

这篇文章的问题是:

很多很好的答案试图解释关于主执行循环的承诺。经过大量的视频和其他不错的阅读后,我现在了解的是:

我的函数init()正确返回。然而,主事件循环中:它返回 ,那是我的工作从内搭上这一承诺的结果

并行循环(不是一个新的真正的线程)。为了从并行循环中获取结果,有两种方法:

  1. 使用 .then( value => doSomethingWithMy(value) )

  2. 使用let value = await myAsyncFn()。现在这是愚蠢的打cup:

await只能在async功能内使用:p

因此它本身返回一个Promise,await应将其嵌入到一个async函数中,该函数将可与awaitetc 一起使用…

这意味着我们不能真正等待Promise:相反,我们应该无限期地捕获并行循环:使用.then()async/await

谢谢您的帮助 !

回答:

您用JavaScript编写的代码在一个线程上运行,这意味着,如果您的代码实际上可以等待某件事,它将阻止您的其他任何代码被执行。

在浏览器中阻止代码的一个很好的例子是alert("cannotdoanythinguntilyouclickok");。Alert阻止了所有内容,用户甚至无法滚动或单击页面中的任何内容,并且您的代码也被阻止执行。

Promise.resolve(22)

.then(x=>alert("blocking")||"Hello World")

.then(

x=>console.log(

"does not resolve untill you click ok on the alert:",

x

)

);

在控制台中运行它,您会明白我所说的阻塞。

当您想做一些需要时间的事情时,这会造成问题。在其他框架中,您将使用线程或进程,但是JavaScript中没有这样的东西(从技术上讲,是在Web

worker和fork in node中存在的,但这是另一回事了,通常比使用异步api复杂得多)。

因此,当您要发出http请求时,可以使用,fetch但fetch需要一些时间才能完成,并且您的函数不应阻塞(必须尽快返回)。这就是为什么访存返回承诺的原因。

请注意,抓取操作是由浏览器/节点实现的,并且确实在另一个线程中运行,只有您编写的代码在一个线程中运行,因此可以保证,仅运行您编写的代码不会加快任何速度,但并行调用本机异步api会加快速度。

在promise之前,异步代码使用了回调或将返回可观察对象(例如XmlHttpRequest),但让我们讨论一下promise,因为您仍然可以将更传统的代码转换为promise。

Promise是一个具有then功能的对象(以及一堆当时是糖的东西,但功能相同),该功能带有2个参数。

  1. 解析处理程序:当承诺解析(没有错误并且完成)时,由承诺调用的函数。该函数将被传递一个带有resolve值的参数(对于http请求,这通常是响应)。
  2. 拒绝处理程序:当诺言被拒绝(有错误)时,诺言将调用的函数。此函数将传递一个参数,通常是错误或拒绝原因(可以是字符串,数字或其他任何东西)。

传统的api(尤其是nodejs api)使用回调:

traditionalApi(

arg

,function callback(err,value){

err ? handleFail(err) : processValue(value);

}

);

这使程序员难以捕捉错误或以线性方式(从上到下)处理返回值。尝试与错误处理并行执行或限制并行处理(不可能读取)变得更加不可能。

您可以将传统的api转换为promise new Promise

const apiAsPromise = arg =>

new Promise(

(resolve,reject)=>

traditionalApi(

arg,

(err,val) => (err) ? reject(err) : resolve(val)

)

)

这就是诺言的语法糖。它使承诺承诺功能看起来更传统,更易于阅读。那就是如果您想编写传统代码,我会认为编写小型函数更容易阅读。例如,您能猜出这是什么吗?:

const handleSearch = search =>

compose([

showLoading,

makeSearchRequest,

processRespose,

hideLoading

])(search)

.then(

undefined,//don't care about the resolve

compose([

showError,

hideLoading

])

);

Anayway;足够的咆哮。重要的部分是要了解asyncawait实际上并没有启动另一个线程,async函数总是返回一个Promise,await并且实际上没有阻塞或等待。它的语法糖someFn().then(result=>...,error=>...),看起来像:

async someMethod = () =>

//syntax sugar for:

//return someFn().then(result=>...,error=>...)

try{

const result = await someFn();

...

}catch(error){

...

}

}

这些示例始终显示,try catch但您不需要这样做,例如:

var alwaysReject = async () => { throw "Always returns rejected promise"; };

alwaysReject()

.then(

x=>console.log("never happens, doesn't resolve")

,err=>console.warn("got rejected:",err)

);

抛出的任何错误或await返回被拒绝的承诺都会导致异步函数返回被拒绝的承诺(除非您尝试抓住它)。很多时候,希望让它失败并让调用者处理错误。

当您希望诺言成功而被拒绝的诺言具有特殊值时,可能会需要捕获错误,以便您可以稍后进行处理,但是诺言在技术上不会拒绝,因此始终可以解决。

一个例子是Promise.all,它接受一个promise数组并返回一个新的promise,该promise解析为一个解析值数组,

。您可能只想获取所有承诺的结果并过滤掉被拒绝的承诺:

const Fail = function(details){this.details=details;},

isFail = item => (item && item.constructor)===Fail;

Promise.all(

urls.map(//map array of urls to array of promises that don't reject

url =>

fetch(url)

.then(

undefined,//do not handle resolve yet

//when you handle the reject this ".then" will return

// a promise that RESOLVES to the value returned below (new Fail([url,err]))

err=>new Fail([url,err])

)

)

)

.then(

responses => {

console.log("failed requests:");

console.log(

responses.filter(//only Fail type

isFail

)

);

console.log("resolved requests:");

console.log(

responses.filter(//anything not Fail type

response=>!isFail(response)

)

);

}

);

以上是 异步函数不返回值,但是console.log()可以:怎么办? 的全部内容, 来源链接: utcz.com/qa/422021.html

回到顶部