Making a promise work inside a JavaScript switch/c

2020-06-17 14:35发布

I having a problem (well two if I'm honest) getting a promise or a callback to work inside a switch-case. Here is the basic code.

switch (page) {

  case 'contact':

   alert('contact in switch');

   var promise = $.get(page +'.json');
   promise.then(function(data){
     console.log("Items back! ", data);                     
   });

  break;
  .......

  console.log("Response data: ", data); // This is undefined

I understand that due to the nature of async functions, the switch is falling through to the break before the data comes back, making data log as undefined. So I thought putting the break inside the callback would work but it doesn't. When I do that the app stops working entirely.

So I guess my first question is how do I make the switch-case "wait" until the data comes back before going to break.

The second problem I have is that I ultimately want to be able to reuse my switch by wrapping it in a function where the page argument is the title of the page the user is navigating to and the callback will pass back the data returned from the getPageData function. When I try this it results in an undefined error for the callback of the pageContentLoaderfunction.

For the record, the getPageDatain the code below is a separate function which performs a generic XMLHttpRequest. It's working fine because the data gets logged correctly in the callback.

pageContentLoader(page, function(data) {
                    console.log("Back with data ", data);   
});

function pageContentLoader(page, callback){
    var data;

            switch (page) {
                case 'contact':
                    console.log('contact in switch');
                    getPageData(page,function(data){
                      console.log("Contacts back! ", data);     
                    });             
                    break;    
                case 'blog':
                    console.log('blog in switch');
                    getPageData(page,function(data){
                        console.log("Posts back! ", data);      
                    });                 
                    break;    
                default:
                    alert('hey that page doesn't exist!');    
            } 
            callback(data); // results in callback undefined!!
}   

I am sure it is possible to make this work but I've tried everything I can find without any luck so far. If anyone has any pointers or wants to tell me what I am doing wrong within my code I'd be grateful!

4条回答
看我几分像从前
2楼-- · 2020-06-17 15:11

Just ran into to this problem earlier, solved it as follows:

async getResolvedPromises(myObject) {
    const promises = await Object.keys(myObject).map(async (k) => {
        switch (k) {
            case '1':
                const firstPromise = await asyncCallNumber1()
                return firstPromise
            case '2':
                const secondPromise = await asyncCallNumber2()
                return secondPromise
            case '3':
                const thirdPromise = await asyncCallNumber3()
                return thirdPromise
            default:
                return
        }
    })

    const data = await Promise.all(promises)
    return data
}
查看更多
家丑人穷心不美
3楼-- · 2020-06-17 15:21

Here's a solution using the Promise constructor:

pageContentLoader('blog').then(function(data)
{
	console.log("Call to pageContentLoader results: ", data);   
});

function pageContentLoader(page)
{
	switch (page) {
		case 'contact':
			return new Promise(function(resolve)
			{
				console.log('contact in switch');
				getPageData(page).then(function(data)
				{
					console.log("pageContentLoader results: ",data);
					resolve(data)
				});
			});
			break;    
		case 'blog':
			return new Promise(function(resolve)
			{
				console.log('blog in switch');
				getPageData(page).then(function(data)
				{
					console.log("pageContentLoader results: ",data);
					resolve(data)
				});
			});
			break;    
		default:
			return new Promise(function(resolve)
			{
				console.log('default in switch');
				console.log("pageContentLoader results: doesn't exist");
				resolve("page doesn't exist");
			});
	} 
}

function getPageData(page)
{
	return new Promise(function(resolve)
	{
		window.setTimeout(function()
		{
			console.log('getPageData executed')
			resolve(page);
		},2000);
	});
}

enter code here
查看更多
甜甜的少女心
4楼-- · 2020-06-17 15:28

For the first problem: You are trying to load a value of something that might not have been defined. As said, you need to think about learning some tips and tricks of asynchronous coding but here's a solution :

  switch (page) {
    case 'contact':
      alert('contact in switch');
      $.get(page +'.json').then(function(data){
        /* all the code AFTER fulfilling 
           the promise should BE here
         */
        handle_data(data);
      });
    break;

  //console.log("Response data: ", data); this should not be here
  ...
查看更多
Root(大扎)
5楼-- · 2020-06-17 15:29

Here's a recent example in Typescript that I've adapted:

private pageContentLoader = async (): Promise<any> => {
    try {
        switch(page) {
            case 'contact':
                return await getPageData(page).then((data) => {
                    console.log("Contacts back! ", data);
                    return data;
                })
            case 'blog':
                return await getPageData(page).then((data) => {
                    console.log("Posts back! ", data);
                    return data;
                })
            default:
                return 'Page does not exist';
        }   
    } catch (err) {
        throw err;
    }
}


private getPageContent = async () => {
    try {
        const contactPageData = await pageContentLoader('contact');
        const blogPageData = await pageContentLoader('blog');
    } catch (err) {
        throw err;
    }
};
查看更多
登录 后发表回答