Promise 保持待处理状态,返回 Null

发布于 2025-01-19 21:04:30 字数 1305 浏览 2 评论 0原文

我正在研究GraphQl查询,我正在尝试找到一个唯一的模型。但是,由于查询完成之前的代码一直在继续,因此什么都没有返回,因此在预期模型时试图回报承诺。代码看起来如下...

          const findShift = async (date) => {
                console.log("In mutation function")
                const foundShift = await db.shift.findUnique({
                    where: {
                        date: date
                    }
                })
                return foundShift
            }
    
            const foundShift = findShift(date).then( resolved => {
                console.log("printing resolved...")
                console.log(resolved)
                if (resolved.id != 'undefined'){
                    console.log({
                        id: resolved.id,
                        date: resolved.date,
                        allDevices: resolved.allDevices
                    })
                    return foundShift
                }
                else{
                    throw new Error("no shift of that date found!")
                }
            })

和console.log语句使控制台看起来像这样...

In mutation function
Promise { <pending> }
prisma:info Starting a postgresql pool with 9 connections.

最终查询只是返回null。如您所见,我尝试使用然后尝试使用,并将突变本身放入完全不同的功能中,只是为了避免这些异步问题而无济于事。有人看到解决方法吗?

I am working on a GraphQL query where I am trying to find a unique model. However, nothing ever gets returned because the code kept carrying on before the query was finished, thus attempted to return a Promise when it expected a Model. The code looks as follows...

          const findShift = async (date) => {
                console.log("In mutation function")
                const foundShift = await db.shift.findUnique({
                    where: {
                        date: date
                    }
                })
                return foundShift
            }
    
            const foundShift = findShift(date).then( resolved => {
                console.log("printing resolved...")
                console.log(resolved)
                if (resolved.id != 'undefined'){
                    console.log({
                        id: resolved.id,
                        date: resolved.date,
                        allDevices: resolved.allDevices
                    })
                    return foundShift
                }
                else{
                    throw new Error("no shift of that date found!")
                }
            })

And the console.log statements make the console look as so...

In mutation function
Promise { <pending> }
prisma:info Starting a postgresql pool with 9 connections.

and ultimately the query just returns null. As you see, I tried using then and putting the mutation itself into an entirely different function just to circumvent these asynchronisity issues to no avail. Does anyone see a workaround?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鹿港巷口少年归 2025-01-26 21:04:30

首先,所有async函数返回承诺。异步函数中的返回值成为该诺言的解决值。因此,async函数的呼叫者必须使用。然后,然后等待从异步函数获取已解析值。像您正在尝试的那样,无法“绕开”异步性。您可以驯服它以使其更有用,但是您无法逃脱它。因此,您的async函数返回待处理的承诺,最终将解决您在async函数中返回的任何值。

您可以阅读有关async函数工作的更多信息在这里在其他答案中。


试图使a 最小,可重复的示例用异步模拟替换为数据库调用:

function delay(t, v) {
    return new Promise(resolve => setTimeout(resolve, t, v));
}

// simulate asynchronous database operation
const db = {
    shift: {
        findUnique: function(data) {
            return delay(100, { id: 123, date: Date.now(), allDevices: ["iPhone", "Galaxy", "Razr"] });
        }
    }
}

const findShift = async (date) => {
    console.log("In mutation function")
    const found = await db.shift.findUnique({
        where: {
            date: date
        }
    })
    return found;
}

const date = Date.now();

const foundShift = findShift(date).then(resolved => {
    console.log("printing resolved...")
    console.log(resolved);
    if (resolved.id != 'undefined') {
        console.log({
            id: resolved.id,
            date: resolved.date,
            allDevices: resolved.allDevices
        })
        return foundShift
    } else {
        throw new Error("no shift of that date found!")
    }
});

当我在nodejs中运行此错误时,我会收到此错误:

[TypeError: Chaining cycle detected for promise #<Promise>]

并且,错误是由这条代码线引起的:

return foundShift

您正在尝试返回该承诺链的一部分,该诺言已经是该承诺链的一部分。承诺链。这会产生不允许的循环依赖性。

您需要返回的是您想要父母承诺的解决价值的一切。由于这看起来像是您在其上方构造的对象,因此我修改了代码来执行此操作。可以运行此代码,fistshift是解决您对象的承诺。

function delay(t, v) {
    return new Promise(resolve => setTimeout(resolve, t, v));
}

// simulate asynchronous database operation
const db = {
    shift: {
        findUnique: function(data) {
            return delay(100, { id: 123, date: Date.now(), allDevices: ["iPhone", "Galaxy", "Razr"] });
        }
    }
}

const findShift = async (date) => {
    const found = await db.shift.findUnique({
        where: {
            date: date
        }
    })
    return found;
}

const date = Date.now();

const foundShift = findShift(date).then(resolved => {
    if (resolved.id != 'undefined') {
        let result = {
            id: resolved.id,
            date: resolved.date,
            allDevices: resolved.allDevices
        };
        return result;
    } else {
        throw new Error("no shift of that date found!")
    }
});

// foundShift here is a promise
// to get it's value, you have to use .then() or await on it
foundShift.then(result => {
    console.log("final result", result);
}).catch(e => {
    console.log(e);
});

以下是有关承诺可能有帮助的承诺的几个规则:

  1. 所有fn()。然后()fn()。catch()返回的fn()
  2. 所有async函数返回承诺。
  3. 您不能“绕开”异步性,并以某种方式直接返回异步检索的值。您必须使用回调,事件或返回承诺(或某些类似的异步机制),以便将异步检索的值与呼叫者交流。
  4. 等待只能在async函数(或在ESM模块的顶级)中使用。
  5. 函数中的第一个等待暂停执行async函数,然后立即向呼叫者返回未实现的承诺。因此,等待仅影响当前功能流,而不影响呼叫者的流程。呼叫者仍然必须使用。然后,然后使用()等待async函数返回的承诺中获取值。
  6. 尽可能尝试这些规则(在JavaScript中,因为它当前在浏览器或nodejs中运行)。

First off, ALL async functions return a promise. The return value in the async function becomes the resolved value of that promise. So, the caller of an async function MUST use .then() or await to get the resolved value from the async function. There is no way to "circumvent" the asynchronicity like you are attempting. You can tame it to make it more usable, but you can't escape it. So, your async function returns a pending promise that will eventually resolve to whatever value you return inside your async function.

You can read more about how async functions work here in this other answer.


In trying to make a minimal, reproducible example of your code, I've reduced it to this where I've substituted an asynchronous simulation for the database call:

function delay(t, v) {
    return new Promise(resolve => setTimeout(resolve, t, v));
}

// simulate asynchronous database operation
const db = {
    shift: {
        findUnique: function(data) {
            return delay(100, { id: 123, date: Date.now(), allDevices: ["iPhone", "Galaxy", "Razr"] });
        }
    }
}

const findShift = async (date) => {
    console.log("In mutation function")
    const found = await db.shift.findUnique({
        where: {
            date: date
        }
    })
    return found;
}

const date = Date.now();

const foundShift = findShift(date).then(resolved => {
    console.log("printing resolved...")
    console.log(resolved);
    if (resolved.id != 'undefined') {
        console.log({
            id: resolved.id,
            date: resolved.date,
            allDevices: resolved.allDevices
        })
        return foundShift
    } else {
        throw new Error("no shift of that date found!")
    }
});

When I run this in nodejs, I get this error:

[TypeError: Chaining cycle detected for promise #<Promise>]

And, the error is caused by this line of code:

return foundShift

You are attempting to return a promise that's already part of this promise chain from within the promise chain. That creates a circular dependency which is not allowed.

What you need to return there is whatever you want the resolved value of the parent promise to be. Since that looks like it's the object you construct right above it, I've modified the code to do that. This code can be run and foundShift is a promise that resolves to your object.

function delay(t, v) {
    return new Promise(resolve => setTimeout(resolve, t, v));
}

// simulate asynchronous database operation
const db = {
    shift: {
        findUnique: function(data) {
            return delay(100, { id: 123, date: Date.now(), allDevices: ["iPhone", "Galaxy", "Razr"] });
        }
    }
}

const findShift = async (date) => {
    const found = await db.shift.findUnique({
        where: {
            date: date
        }
    })
    return found;
}

const date = Date.now();

const foundShift = findShift(date).then(resolved => {
    if (resolved.id != 'undefined') {
        let result = {
            id: resolved.id,
            date: resolved.date,
            allDevices: resolved.allDevices
        };
        return result;
    } else {
        throw new Error("no shift of that date found!")
    }
});

// foundShift here is a promise
// to get it's value, you have to use .then() or await on it
foundShift.then(result => {
    console.log("final result", result);
}).catch(e => {
    console.log(e);
});

Here are a couple of rule about promises that might help:

  1. All fn().then() or fn().catch() calls return a new promise that is chained to the one that fn() returned.
  2. All async functions return a promise.
  3. You cannot "circumvent" asynchronicity and somehow directly return an asynchronously retrieved value. You will have to use a callback, an event or return a promise (or some similar asynchronous mechanism) in order to communicate back to the caller an asynchronously retrieved value.
  4. await can only be used inside an async function (or at the top level of an ESM module).
  5. The first await in a function suspends execution of the async function and then immediately returns an unfulfilled promise to the caller. So, the await only affects the current function flow, not the caller's flow. The caller will still have to use .then() or await to get the value out of the promise that the async function returns.
  6. Try as you might, there is no way around these rules (in Javascript as it currently runs in a browser or in nodejs).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文