약속을 여러 번 해결하는 것이 안전한가?
어플리케이션에 다음 코드가 포함된 i18n 서비스가 있습니다.
var i18nService = function() {
this.ensureLocaleIsLoaded = function() {
if( !this.existingPromise ) {
this.existingPromise = $q.defer();
var deferred = this.existingPromise;
var userLanguage = $( "body" ).data( "language" );
this.userLanguage = userLanguage;
console.log( "Loading locale '" + userLanguage + "' from server..." );
$http( { method:"get", url:"/i18n/" + userLanguage, cache:true } ).success( function( translations ) {
$rootScope.i18n = translations;
deferred.resolve( $rootScope.i18n );
} );
}
if( $rootScope.i18n ) {
this.existingPromise.resolve( $rootScope.i18n );
}
return this.existingPromise.promise;
};
가 ""를 것입니다.ensureLocaleIsLoaded
약속이 풀릴 때까지 기다리겠습니다.단, 이 함수의 목적은 로케일이 로딩되어 있는지 확인하는 것뿐이므로 사용자가 여러 번 로케일을 호출해도 문제 없습니다.
현재 하나의 약속만 저장하고 있으며, 서버에서 로케일이 정상적으로 검색된 후 사용자가 함수를 다시 호출하면 해결합니다.
제가 봤을 때, 이것은 의도대로 작동하고 있는 것 같습니다만, 이것이 적절한 어프로치인지 궁금합니다.
현시점에서는 약속대로라면 100% OK입니다.이해해야 할 유일한 것은 일단 해결(또는 거부)되면 배변된 물체에 대한 것으로, 그것은 완료된다는 것입니다.
「 」에 then(...)
다시 한번 약속하면, 즉시 해결/불합치한 결과를 얻을 수 있습니다.
에 대한 콜resolve()
아무 효과도 없을 겁니다.
다음은 이러한 사용 사례에 대한 실행 가능한 스니펫입니다.
var p = new Promise((resolve, reject) => {
resolve(1);
reject(2);
resolve(3);
});
p.then(x => console.log('resolved to ' + x))
.catch(x => console.log('never called ' + x));
p.then(x => console.log('one more ' + x));
p.then(x => console.log('two more ' + x));
p.then(x => console.log('three more ' + x));
했지만, 은 한되고, 한 번 이 없다( 경고도 않는다). 사실 약속은 한 번만 해결된다. 또 한 번 시도해도 아무 소용이 없다(오류도 경고도 하지 않는다.then
★★★★★★★★★★★★★★★★★★」
저는 이렇게 해결하기로 했습니다.
getUsers(users => showThem(users));
getUsers(callback){
callback(getCachedUsers())
api.getUsers().then(users => callback(users))
}
기능을 콜백으로 전달하고 원하는 횟수만큼 호출하기만 하면 됩니다.그게 말이 됐으면 좋겠어요.
약속은 해결되었으므로 여러 번 해결할 수 있는 명확한 방법은 없습니다.여기서 더 나은 방법은 관찰자-관찰 가능한 패턴을 사용하는 것입니다. 예를 들어 소켓클라이언트 이벤트를 관찰하는 다음 코드를 작성합니다.필요에 따라 이 코드를 확장할 수 있습니다.
const evokeObjectMethodWithArgs = (methodName, args) => (src) => src[methodName].apply(null, args);
const hasMethodName = (name) => (target = {}) => typeof target[name] === 'function';
const Observable = function (fn) {
const subscribers = [];
this.subscribe = subscribers.push.bind(subscribers);
const observer = {
next: (...args) => subscribers.filter(hasMethodName('next')).forEach(evokeObjectMethodWithArgs('next', args))
};
setTimeout(() => {
try {
fn(observer);
} catch (e) {
subscribers.filter(hasMethodName('error')).forEach(evokeObjectMethodWithArgs('error', e));
}
});
};
const fromEvent = (target, eventName) => new Observable((obs) => target.on(eventName, obs.next));
fromEvent(client, 'document:save').subscribe({
async next(document, docName) {
await writeFilePromise(resolve(dataDir, `${docName}`), document);
client.emit('document:save', document);
}
});
해야 할 새 하십시오.then
에 쇠사슬을 매다then
/catch
있다
var p1 = new Promise((resolve, reject) => { resolve(1) });
var p2 = p1.then(v => {
console.log("First then, value is", v);
return 2;
});
p2.then(v => {
console.log("Second then, value is", v);
});
동작을 확인하기 위한 테스트를 작성할 수 있습니다.
다음 테스트를 실행하면 다음과 같은 결론을 내릴 수 있습니다.
resolve()/reject() 콜의 never throw 에러가 발생했습니다.
해결(거부)되면 해결된 값(거부된 오류)은 다음 resolve() 또는 reject() 호출에 관계없이 유지됩니다.
자세한 내용은 제 블로그 투고에서도 확인하실 수 있습니다.
/* eslint-disable prefer-promise-reject-errors */
const flipPromise = require('flip-promise').default
describe('promise', () => {
test('error catch with resolve', () => new Promise(async (rs, rj) => {
const getPromise = () => new Promise(resolve => {
try {
resolve()
} catch (err) {
rj('error caught in unexpected location')
}
})
try {
await getPromise()
throw new Error('error thrown out side')
} catch (e) {
rs('error caught in expected location')
}
}))
test('error catch with reject', () => new Promise(async (rs, rj) => {
const getPromise = () => new Promise((_resolve, reject) => {
try {
reject()
} catch (err) {
rj('error caught in unexpected location')
}
})
try {
await getPromise()
} catch (e) {
try {
throw new Error('error thrown out side')
} catch (e){
rs('error caught in expected location')
}
}
}))
test('await multiple times resolved promise', async () => {
const pr = Promise.resolve(1)
expect(await pr).toBe(1)
expect(await pr).toBe(1)
})
test('await multiple times rejected promise', async () => {
const pr = Promise.reject(1)
expect(await flipPromise(pr)).toBe(1)
expect(await flipPromise(pr)).toBe(1)
})
test('resolve multiple times', async () => {
const pr = new Promise(resolve => {
resolve(1)
resolve(2)
resolve(3)
})
expect(await pr).toBe(1)
})
test('resolve then reject', async () => {
const pr = new Promise((resolve, reject) => {
resolve(1)
resolve(2)
resolve(3)
reject(4)
})
expect(await pr).toBe(1)
})
test('reject multiple times', async () => {
const pr = new Promise((_resolve, reject) => {
reject(1)
reject(2)
reject(3)
})
expect(await flipPromise(pr)).toBe(1)
})
test('reject then resolve', async () => {
const pr = new Promise((resolve, reject) => {
reject(1)
reject(2)
reject(3)
resolve(4)
})
expect(await flipPromise(pr)).toBe(1)
})
test('constructor is not async', async () => {
let val
let val1
const pr = new Promise(resolve => {
val = 1
setTimeout(() => {
resolve()
val1 = 2
})
})
expect(val).toBe(1)
expect(val1).toBeUndefined()
await pr
expect(val).toBe(1)
expect(val1).toBe(2)
})
})
메인 ng 콘센트에 ng-if를 붙이고 대신 로딩 스피너를 표시해야 합니다.로케일이 로딩되면 아웃렛을 표시하고 컴포넌트 계층이 렌더링되도록 합니다.이렇게 하면 모든 응용 프로그램이 로케일이 로드되어 검사가 필요하지 않다고 가정할 수 있습니다.
아니요. 약속을 여러 번 해결하거나 거부하는 것은 안전하지 않습니다.기본적으로는 버그로, 항상 재현할 수 있는 것은 아니기 때문에 잡기 어렵습니다.
디버깅 시 이러한 문제를 추적하기 위해 사용할 수 있는 패턴이 있습니다.이 주제에 대한 훌륭한 강의: Ruben Bridgewater — 오류 처리: 올바르게 하기! (질문과 관련된 부분은 약 40분)
github gest: reuse_module을 참조하십시오.js
/*
reuse a promise for multiple resolve()s since promises only resolve once and then never again
*/
import React, { useEffect, useState } from 'react'
export default () => {
const [somePromise, setSomePromise] = useState(promiseCreator())
useEffect(() => {
somePromise.then(data => {
// do things here
setSomePromise(promiseCreator())
})
}, [somePromise])
}
const promiseCreator = () => {
return new Promise((resolve, reject) => {
// do things
resolve(/*data*/)
})
}
언급URL : https://stackoverflow.com/questions/20328073/is-it-safe-to-resolve-a-promise-multiple-times
'sourcecode' 카테고리의 다른 글
투고를 워드프레스에 삽입하여 카테고리와 관련지으려면 어떻게 해야 합니까? (0) | 2023.03.14 |
---|---|
Resangular vs. JSData(기존 Angular 데이터) 비교 (0) | 2023.03.14 |
Google Angular 지도JS (0) | 2023.03.14 |
각도로 ng-repeat을 사용하여 100개 중 6개에서 10개까지의 결과를 필터링합니다.JS (0) | 2023.03.14 |
지도 함수 내에서 "this"가 정의되지 않았습니다. Reactjs (0) | 2023.03.14 |