gpt4 book ai didi

javascript - 异步函数不返回值,但 console.log() 执行 : how to do?

转载 作者:数据小太阳 更新时间:2023-10-29 05:03:27 25 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





How to return the response from an asynchronous call

(42 个回答)


3年前关闭。




我有一个 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/await init() 中的机制方法。
现在,此代码将正常工作:
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但不是最终值。我已经阅读了几篇关于这个主题的相关文章,但它们都给出了日志记录的例子,再也没有回来。

Here is a fiddle包括两种处理方式 init() :使用 Promise并使用 async/await .无论我尝试什么,我都无法使用 getPostById(id) 的最终值.

这个帖子的问题是: 我如何创建一个函数来返回 getPostById(id) 的值?

编辑:

很多很好的答案试图解释关于主执行循环的 Promises 是什么。
经过大量视频和其他好的阅读,以下是我现在的理解:

我的函数 init()正确返回。然而,在主事件循环中:它返回 一个 promise ,那么我的工作就是从 中获取这个 Promise 的结果。有点 并行循环(不是新的真正线程)。为了从并行循环中捕获结果,有两种方法:
  • 使用 .then( value => doSomethingWithMy(value) )
  • 使用 let value = await myAsyncFn() .现在这是愚蠢的打嗝:

  • await can only be used within an async function :p



    因此本身返回一个 Promise,可用于 await应该嵌入到 async 中函数,可用于 await等等...

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

    谢谢您的帮助 !

    最佳答案

    至于你的评论;我将其添加为答案。

    您用 JavaScript 编写的代码在一个线程上运行,这意味着如果您的代码实际上可以等待某些东西,它将阻止您执行任何其他代码。 JavaScript 的事件循环在 this video 中有很好的解释如果您喜欢阅读 this page .

    在浏览器中阻止代码的一个很好的例子是 alert("cannot do anything until you click ok"); .警报会阻止所有内容,用户甚至无法滚动或单击页面中的任何内容,您的代码也会阻止执行。

    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,但这是另一回事,通常比使用异步 api 复杂得多)。

    因此,当您想发出 http 请求时,您可以使用 fetch但是 fetch 需要一些时间才能完成,并且您的函数不应阻塞(必须尽快返回某些内容)。这就是 fetch 返回一个 promise 的原因。

    请注意,fetch 是由浏览器/节点实现的,并且确实在另一个线程中运行,只有您编写的代码在一个线程中运行,因此启动大量仅运行您编写的代码的 promise 不会加快任何速度,但会并行调用 native 异步 api。

    在 promise 之前异步代码使用回调或返回一个可观察对象(如 XmlHttpRequest),但让我们介绍一下 promise,因为无论如何您都可以将更传统的代码转换为 promise。

    promise 是具有 then 的对象。函数(还有一堆东西是糖,但做同样的事情),这个函数需要 2 个参数。
  • 解析处理程序:当 promise 解决(没有错误并完成)时将由 promise 调用的函数。该函数将传递一个带有解析值的参数(对于 http 请求,这通常是响应)。
  • 拒绝处理程序:当 promise 拒绝(有错误)时由 promise 调用的函数。这个函数将传递一个参数,这通常是错误或拒绝的原因(可以是字符串、数字或任何东西)。

  • 将回调转换为 promise 。

    传统的 api(尤其是 nodejs api)使用回调:
    traditionalApi(
    arg
    ,function callback(err,value){
    err ? handleFail(err) : processValue(value);
    }
    );

    这使得程序员很难以线性方式(从上到下)捕获错误或处理返回值。尝试与错误处理并行或节流并行处理事情变得更加不可能(无法阅读)。

    您可以使用 new Promise 将传统的 api 转换为 promises
    const apiAsPromise = arg =>
    new Promise(
    (resolve,reject)=>
    traditionalApi(
    arg,
    (err,val) => (err) ? reject(err) : resolve(val)
    )
    )

    异步等待

    这就是所谓的 promise 的语法糖。它使 Promise 消费函数看起来更传统且更易于阅读。也就是说,如果您喜欢编写传统代码,我认为组合小函数更容易阅读。例如,你能猜出这是做什么的吗?:
    const handleSearch = search =>
    compose([
    showLoading,
    makeSearchRequest,
    processRespose,
    hideLoading
    ])(search)
    .then(
    undefined,//don't care about the resolve
    compose([
    showError,
    hideLoading
    ])
    );

    无论如何;足够的咆哮。重要的是要了解 async await实际上并没有启动另一个线程, 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 将导致异步函数返回一个被拒绝的 promise (除非你试图捕获它)。很多时候希望让它失败并让调用者处理错误。

    当您希望 promise 成功并为被拒绝的 promise 设置特殊值时,可能需要捕获错误,以便您可以稍后处理它,但 promise 在技术上不会拒绝,因此将始终解决。

    一个例子是 Promise.all ,这需要一个 promise 数组并返回一个新的 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)
    )
    );
    }
    );

    关于javascript - 异步函数不返回值,但 console.log() 执行 : how to do?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47664598/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com