2016-08-29 3 views
0

함수 발생기GraphQL 변이 안에 사용하는 데 문제가 있습니다.GraphQL의 outputFields에 대한 반환 값 함수 생성기를 사용하는 변이

함수 발생기는 돌연변이 내부의 약속 체인을 정리하는 데 사용됩니다. 리팩터링하기 전에 코드가 정상적으로 작동하고 있었고 현재 console.logs은 데이터베이스에 새로 작성된 쓰기를 보여 주므로 함수 생성기에서 최종 반환 값을 가져 와서 반환 값으로 설정한다고 말할 수 있습니다. mutateAndGetPayload 기능.

이 재산 'clientMutationId'정의되지 않은

지금이 잠시 동안 있었다의를 설정할 수 없습니다 어떤 조언이나 도움을 주셔서 감사합니다 것입니다 오류가 발생했습니다.

함수 발생기의 반환 값을 둘러싸는 함수의 범위로 가져와 함수에서 반환 할 수 있습니까?


아래는 돌연변이이다. 데이타베이스는 잘 동작하며 출력은 올바른 페이로드를 얻을 때 작동합니다 (작동하지 않습니다. 이것이 내 주요 문제입니다). 유일한 문제는 newUser을 출력 필드의 resolve 함수로 가져 오는 것입니다. 문제를 간단하게하기 위해 일부 코드를 생략했습니다. @Bergi의 도움을

const addEmployeeMutation = mutationWithClientMutationId({ 
    name: 'AddEmployee', 
    inputFields: { 
    /** this section works fine **/ 
    }, 
    outputFields: { 
    attendee: { 
     type: AttendeeType, 
     resolve: r.compose(
      /** this section works fine **/ 
      r.prop('id') 
     ) 
    } 
    }, 
    mutateAndGetPayload: (payload, {userId}) => { 
    const getUser = (userId) => { 
     return authorize(userId) 
     .then(can => /** works fine **/) 
     .then(user => gen.next(user)) 
    }  
    const createHash = (plainPassword) => { 
     return genSalt(10) 
     .then((salt, err) => { /** works fine **/ }) 
     .then((hashed_password, err) => gen.next(hashed_password)) 
    } 
    const createUser = (payload, hashed_password, user) => { 
     return new UserModel(/** works fine **/).save() 
     .then(newUser => gen.next(newUser)) 
    }  
    const createProfile = (payload, newUserId) => { 
     return new ProfileModel({ /** works fine **/ }) 
     .then(profile => gen.next(profile)) 
     .catch(err => {throw new GraphQLError(`Error: ${err}`)}) 
    } 
    let gen = generator() 
    gen.next()  
    function* generator() { 
     const user = yield getUser(userId) 
     console.log('USER >>>>>>>>>>>>>>>>>>', user) 
     const hash = yield createHash(payload.password) 
     console.log('HASH >>>>>>>>>>>>>>>>>>', hash) 
     const newUser = yield createUser(payload, hash, user) 
     console.log('NEW USER >>>>>>>>>>>>>>>>>> ', newUser)  
     const newProfile = yield createProfile(payload, newUser.id) 
     console.log('NEW PROFILE >>>>>>>>>>>>>>>>>> ', newProfile)  
     return newUser 
    } 
    return newUser // <- How do I get a value to here? 
} 
+1

값을 얻을 수 없습니다. 생성자는 비동기 코드를 동 기적으로 실행하도록 만들지 않으며 다른 것은 없습니다. Btw, 당신은'async' /'await'을 사용해야합니다. 이것은 손으로 작성한 코 루틴 러너보다 훨씬 쉽게 작업 할 수 있습니다. – Bergi

+0

생성자가 출력량을 완료하기 전에 mutateAndGetPayload가 정의되지 않은 값을 반환하는 것처럼 보입니까? 나는 그것이 포함 된 기능을 유지할 것이지만. 여기서 추측하고 있지만, 해결 함수 내에서 생성기를 실행할 수 있다면 작동 할 수도 있지만이 경우에는 갈 길이 멀지 않습니다. 감사합니다 @Bergi 나는'async' /'await'을 시도해 볼 것이고 재미 있다면 여기에 결과를 게시 할 것입니다. – alexi2

+1

예, 생성기를 비동기 적으로 실행하므로 함수가 완료되기 전에 반환됩니다. 당신이 할 수있는 것은 최종 결과에 대한 약속을 되돌려주는 것입니다 (그리고 그것은'비동기 함수'도 마찬가지입니다). – Bergi

답변

1

비동기 기다리고 있습니다

덕분에 나는 async/await를 사용으로 변경되었습니다.

다른 사람이이 길을 가다가 손을 들어 줄 경우를 대비하여 여기에 내 답변을 게시하고 있습니다.

대답은 빠른 수정 인 것으로 나타났습니다.

데이터베이스 쓰기를 수행중인 각 약속에서 .then()을 변경하여 필요한 개체를 반환하십시오. 그런 다음 이들을 별도의 유틸리티 모듈로 옮겼습니다.

mutateAndGetPayload: (payload, {userId}) => { 
    async function generateUser() { 
    const user = await getUser(userId) 
    const hash = await createHash(payload.password) 
    const newUser = await createUser(payload, hash, user) 
    await createProfile(payload, newUser.id) 
    return newUser 
    } 
    return generateUser() 
} 

편집

이보다 깔끔한 해결책 : 돌연변이 자체가 내가 비동기 쓰기를 통해 실행하고 출력 필드에 필요한 페이로드를 반환하려면 다음 코드를 사용

다시 @Bergi에게 감사드립니다. async/await을 사용하는 방법에 대한 명확성을 제공하고 간결함을 개선하기 위해 코드를 리팩터링하는 방법을 보여주기 때문에 원본 솔루션을 남겨두고 있습니다. 다시 말하지만, 누군가는 이것을 유용하게 생각할 것입니다.영업에 함수 발생기의 사용으로


설명

mutateAndGetPayload: async function(payload, {userId}) { 
    const user = await getUser(userId) 
    const hash = await createHash(payload.password) 
    const newUser = await createUser(payload, hash, user) 
    await createProfile(payload, newUser.id) 
    return newUser 
} 
발전기 완료 시간이 없었 전에 mutateAndGetPayload 기능은 undefined를 반환하고, 비동기 따라서 비 차단했다 . async/ await (두 버전 모두)을 사용하여 await 값이 지정된 순서대로 해결 될 때까지 mutateAndGetPayload 함수가 완료되지 못했습니다.

+1

사실'generateUser' 내부 함수를 삭제하고'mutateAndGetPayload' 자체를'async' 자체로 만들어야합니다. – Bergi

+0

다시 한번 @Bergi. 나는이 과정을 보여주기 위해 원래 버전을 남겨 두었고, 이것은'RelayJS'' GraphQL' 돌연변이 내에서 처음으로이 패턴에 오는 사람들을 도울 것입니다. – alexi2

0

Ramda JS

ramda 함수형 프로그래밍 라이브러리를 사용한다 또 다른 방법. 약속을 관리하는 데 도움이되는 q.

ramda.js를 사용하면 데이터가 올바른 순서로 오기를 기다리는 유틸리티 기능이 실행됩니다.

mutateAndGetPayload: (payload, {userId}) => 
    r.compose(
    then(
     r.compose(
     then(r.last), 
     r.converge(
      r.unapply(q.all), 
      [ 
      createProfile(payload), 
      createUserRole(payload), 
      r.identity 
      ] 
     ) 
    ) 
    ), 
    r.converge(
     r.compose(
     then(createUser(payload)), 
     r.unapply(q.all) 
    ), 
     [ 
     r.identity, 
     then(_ => createHash(payload)) 
     ] 
    ), 
    getUser 
)(userId)